{
  "cells": [
    {
      "cell_type": "raw",
      "metadata": {},
      "source": [
        "---\n",
        "title: Mojo🔥 programming manual (deprecated)\n",
        "sidebar_label: Programming manual\n",
        "description: A tour of major Mojo language features with code examples.\n",
        "website:\n",
        "  open-graph:\n",
        "    image: /static/images/mojo-social-card.png\n",
        "  twitter-card:\n",
        "    image: /static/images/mojo-social-card.png\n",
        "---\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[//]: # REMOVE_FOR_WEBSITE\n",
        "*Copyright 2023 Modular, Inc: Licensed under the Apache License v2.0 with LLVM Exceptions.*"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[//]: # REMOVE_FOR_WEBSITE\n",
        "# Mojo🔥 programming manual"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-block alert-warning alert--warning\">\n",
        "\n",
        "<b>DEPRECATED</b>: This document is no longer maintained. We recommend that you\n",
        "instead see the new <a href=\"https://docs.modular.com/mojo/manual/\">Mojo Manual</a>.\n",
        "\n",
        "</div>"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "Mojo is a programming language that is as easy to use as Python but with the\n",
        "performance of C++ and Rust. Furthermore, Mojo provides the ability to leverage\n",
        "the entire Python library ecosystem.\n",
        "\n",
        "Mojo achieves this feat by utilizing next-generation compiler technologies with\n",
        "integrated caching, multithreading, and cloud distribution technologies.\n",
        "Furthermore, Mojo's autotuning and compile-time metaprogramming features allow\n",
        "you to write code that is portable to even the most exotic hardware.\n",
        "\n",
        "More importantly, **Mojo allows you to leverage the entire Python ecosystem**\n",
        "so you can continue to use tools you are familiar with. Mojo is designed to\n",
        "become a **superset** of Python over time by preserving Python's dynamic\n",
        "features while adding new primitives for [systems\n",
        "programming](https://en.wikipedia.org/wiki/Systems_programming). These new\n",
        "system programming primitives will allow Mojo developers to build\n",
        "high-performance libraries that currently require C, C++, Rust, CUDA, and other\n",
        "accelerator systems. By bringing together the best of dynamic languages and\n",
        "systems languages, we hope to provide a **unified** programming model that\n",
        "works across levels of abstraction, is friendly for novice programmers, and\n",
        "scales across many use cases from accelerators through to application\n",
        "programming and scripting.\n",
        "\n",
        "This document is an introduction to the Mojo programming language, not a\n",
        "complete language guide. It assumes knowledge of Python and systems programming\n",
        "concepts. At the moment, Mojo is still a work in progress and the documentation\n",
        "is targeted to developers with systems programming experience. As the language\n",
        "grows and becomes more broadly available, we intend for it to be friendly and\n",
        "accessible to everyone, including beginner programmers. It's just not there\n",
        "today.\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Using the Mojo compiler\n",
        "\n",
        "With the [Mojo SDK](https://docs.modular.com/mojo/manual/get-started/), you can\n",
        "run a Mojo program from a terminal just like you can with Python. So if you\n",
        "have a file named `hello.mojo` (or `hello.🔥`—yes, the file extension can be an\n",
        "emoji!), just type `mojo hello.mojo`:\n",
        "\n",
        "```mojo\n",
        "$ cat hello.🔥\n",
        "def main():\n",
        "    print(\"hello world\")\n",
        "    for x in range(9, 0, -3):\n",
        "        print(x)\n",
        "$ mojo hello.🔥\n",
        "hello world\n",
        "9\n",
        "6\n",
        "3\n",
        "$\n",
        "```\n",
        "\n",
        "Again, you can use either the `.🔥` or `.mojo` suffix.\n",
        "\n",
        "For more details about the Mojo compiler tools, see the [`mojo` CLI\n",
        "docs](https://docs.modular.com/mojo/cli/)."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Basic systems programming extensions\n",
        "\n",
        "Given our goal of compatibility and Python's strength with high-level\n",
        "applications and dynamic APIs, we don't have to spend much time explaining\n",
        "how those portions of the language work. On the other hand, Python's support\n",
        "for systems programming is mainly delegated to C, and we want to provide a\n",
        "single system that is great in that world. As such, this section breaks down\n",
        "each major component and feature and describes how to use them with examples.\n",
        "\n",
        "### `let` and `var` declarations\n",
        "\n",
        "Inside a `def` in Mojo, you may assign a value to a name and it implicitly\n",
        "creates a function scope variable just like in Python. This provides a very\n",
        "dynamic and low-ceremony way to write code, but it is a challenge for two\n",
        "reasons:\n",
        "\n",
        "1) Systems programmers often want to declare that a value is immutable for\n",
        "    type-safety and performance.\n",
        "2) They may want to get an error if they mistype a variable name in an\n",
        "    assignment.\n",
        "\n",
        "To support this, Mojo provides scoped runtime value declarations: `let` is\n",
        "immutable, and `var` is mutable. These values use lexical scoping and support\n",
        "name shadowing:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3\n"
          ]
        }
      ],
      "source": [
        "def your_function(a, b):\n",
        "    var c = a\n",
        "    # Uncomment to see an error:\n",
        "    # c = b  # error: c is immutable\n",
        "\n",
        "    if c != b:\n",
        "        var d = b\n",
        "        print(d)\n",
        "\n",
        "your_function(2, 3)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "`let` and `var` declarations support type specifiers as well as patterns, and\n",
        "late initialization:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "1.0\n"
          ]
        }
      ],
      "source": [
        "def your_function():\n",
        "    var x: Int = 42\n",
        "    var y: Float64 = 17.0\n",
        "\n",
        "    var z: Float32\n",
        "    if x != 0:\n",
        "        z = 1.0\n",
        "    else:\n",
        "        z = foo()\n",
        "    print(z)\n",
        "\n",
        "def foo() -> Float32:\n",
        "    return 3.14\n",
        "\n",
        "your_function()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note that `let` and `var` are completely optional when in a `def` function\n",
        "(you can instead use implicitly declared values, just like Python),\n",
        "but they're required for all variables in an `fn` function.\n",
        "\n",
        "Also beware that when using Mojo in a REPL environment (such as this notebook),\n",
        "top-level variables (variables that live outside a function or struct) are\n",
        "treated like variables in a `def`, so they allow implicit value type\n",
        "declarations (they do not require `var` or `let` declarations, nor type\n",
        "declarations). This matches the Python REPL behavior.\n",
        "\n",
        "### `struct` types\n",
        "\n",
        "Mojo is based on MLIR and LLVM, which offer a cutting-edge compiler and code\n",
        "generation system used in many programming languages. This lets us have better\n",
        "control over data organization, direct access to data fields, and other ways to\n",
        "improve performance. An important feature of modern systems programming\n",
        "languages is the ability to build high-level and safe abstractions on top of\n",
        "these complex, low-level operations without any performance loss. In Mojo, this\n",
        "is provided by the `struct` type.\n",
        "\n",
        "A `struct` in Mojo is similar to a Python `class`: they both support methods,\n",
        "fields, operator overloading, decorators for metaprogramming, etc. Their\n",
        "differences are as follows:\n",
        "\n",
        "- Python classes are dynamic: they allow for dynamic dispatch, monkey-patching\n",
        "(or \"swizzling\"), and dynamically binding instance properties at runtime.\n",
        "\n",
        "- Mojo structs are static: they are bound at compile-time (you cannot add\n",
        "methods at runtime). Structs allow you to trade flexibility for performance\n",
        "while being safe and easy to use.\n",
        "\n",
        "Here's a simple definition of a struct:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct MyPair:\n",
        "    var first: Int\n",
        "    var second: Int\n",
        "\n",
        "    # We use 'fn' instead of 'def' here - we'll explain that soon\n",
        "    fn __init__(inout self, first: Int, second: Int):\n",
        "        self.first = first\n",
        "        self.second = second\n",
        "\n",
        "    fn __lt__(self, rhs: MyPair) -> Bool:\n",
        "        return self.first < rhs.first or\n",
        "              (self.first == rhs.first and\n",
        "               self.second < rhs.second)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Syntactically, the biggest difference compared to a Python `class` is that all\n",
        "instance properties in a `struct` **must** be explicitly declared with a `var`\n",
        "or `let` declaration.\n",
        "\n",
        "In Mojo, the structure and contents of a \"struct\" are set in advance and can't\n",
        "be changed while the program is running. Unlike in Python, where you can add,\n",
        "remove, or change attributes of an object on the fly, Mojo doesn't allow that\n",
        "for structs. This means you can't use `del` to remove a method or change its\n",
        "value in the middle of running the program.\n",
        "\n",
        "However, the static nature of `struct` has some great benefits! It helps Mojo\n",
        "run your code faster. The program knows exactly where to find the struct's\n",
        "information and how to use it without any extra steps or delays.\n",
        "\n",
        "Mojo's structs also work really well with features you might already know from\n",
        "Python, like operator overloading (which lets you change how math symbols like\n",
        "`+` and `-` work with your own data). Furthermore, *all* the \"standard types\"\n",
        "(like `Int`, `Bool`, `String` and even `Tuple`) are made using structs. This\n",
        "means they're part of the standard set of tools you can use, rather than being\n",
        "hardwired into the language itself. This gives you more flexibility and control\n",
        "when writing your code.\n",
        "\n",
        "<div class=\"alert alert-block alert-success alert--secondary\">\n",
        "\n",
        "If you're wondering what the `inout` means on the `self` argument: this\n",
        "indicates that the argument is mutable and changes made inside the function are\n",
        "visible to the caller. For details, see below about\n",
        "[inout arguments](#mutable-arguments-inout).\n",
        "\n",
        "</div>"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### `Int` vs `int`\n",
        "\n",
        "In Mojo, you might notice that we use `Int` (with a capital \"I\"), which is\n",
        "different from Python's `int` (with a lowercase \"i\"). This difference is on\n",
        "purpose, and it's actually a good thing!\n",
        "\n",
        "In Python, the `int` type can handle really big numbers and has some extra\n",
        "features, like checking if two numbers are the same object. But this comes with\n",
        "some extra baggage that can slow things down. Mojo's `Int` is different. It's\n",
        "designed to be simple, fast, and tuned for your computer's hardware to handle\n",
        "quickly.\n",
        "\n",
        "We made this choice for two main reasons:\n",
        "\n",
        "1. We want to give programmers who need to work closely with computer hardware\n",
        "(systems programmers) a transparent and reliable way to interact with hardware.\n",
        "We don't want to rely on fancy tricks (like JIT compilers) to make things\n",
        "faster.\n",
        "\n",
        "2. We want Mojo to work well with Python without causing any issues. By using a\n",
        "different name (Int instead of int), we can keep both types in Mojo without\n",
        "changing how Python's int works.\n",
        "\n",
        "As a bonus, `Int` follows the same naming style as other custom data types you\n",
        "might create in Mojo. Additionally, `Int` is a `struct` that's included in\n",
        "Mojo's standard set of tools.\n",
        "\n",
        "### Strong type checking\n",
        "\n",
        "Even though you can still use flexible types like in Python, Mojo lets you use\n",
        "strict type checking. Type-checking can make your code more predictable,\n",
        "manageable, and secure.\n",
        "\n",
        "One of the primary ways to employ strong type checking is with Mojo's `struct`\n",
        "type. A `struct` definition in Mojo defines a compile-time-bound name, and\n",
        "references to that name in a type context are treated as a strong specification\n",
        "for the value being defined. For example, consider the following code that uses\n",
        "the `MyPair` struct shown above:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [],
      "source": [
        "def pair_test() -> Bool:\n",
        "    var p = MyPair(1, 2)\n",
        "    # Uncomment to see an error:\n",
        "    # return p < 4 # gives a compile time error\n",
        "    return True\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you uncomment the first return statement and run it, you’ll get a\n",
        "compile-time error telling you that `4` cannot be converted to `MyPair`, which\n",
        "is what the right-hand-side of `__lt__()` requires (in the `MyPair` definition).\n",
        "\n",
        "This is a familiar experience when working with systems programming languages,\n",
        "but it's not how Python works. Python has syntactically identical features for\n",
        "[MyPy](https://mypy.readthedocs.io/) type annotations, but they are not\n",
        "enforced by the compiler: instead, they are hints that inform static analysis.\n",
        "By tying types to specific declarations, Mojo can handle both the classical\n",
        "type annotation hints and strong type specifications without breaking\n",
        "compatibility.\n",
        "\n",
        "Type checking isn't the only use-case for strong types. Since we know the types\n",
        "are accurate, we can optimize the code based on those types, pass values in\n",
        "registers, and be as efficient as C for argument passing and other low-level\n",
        "details. This is the foundation of the safety and predictability guarantees\n",
        "Mojo provides to systems programmers.\n",
        "\n",
        "### Overloaded functions and methods\n",
        "\n",
        "Like Python, you can define functions in Mojo without specifying argument data\n",
        "types and Mojo will handle them dynamically. This is nice when you want\n",
        "expressive APIs that just work by accepting arbitrary inputs and let dynamic\n",
        "dispatch decide how to handle the data. However, when you want to ensure type\n",
        "safety, as discussed above, Mojo also offers full support for overloaded\n",
        "functions and methods.\n",
        "\n",
        "This allows you to define multiple functions with the same name but with\n",
        "different arguments. This is a common feature seen in many languages, such as\n",
        "C++, Java, and Swift.\n",
        "\n",
        "When resolving a function call, Mojo tries each candidate and uses the one that\n",
        "works (if only one works), or it picks the closest match (if it can determine a\n",
        "close match), or it reports that the call is ambiguous if it can't figure\n",
        "out which one to pick. In the latter case, you can resolve the ambiguity by\n",
        "adding an explicit cast on the call site. \n",
        "\n",
        "Let's look at an example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct Complex:\n",
        "    var re: Float32\n",
        "    var im: Float32\n",
        "\n",
        "    fn __init__(inout self, x: Float32):\n",
        "        \"\"\"Construct a complex number given a real number.\"\"\"\n",
        "        self.re = x\n",
        "        self.im = 0.0\n",
        "\n",
        "    fn __init__(inout self, r: Float32, i: Float32):\n",
        "        \"\"\"Construct a complex number given its real and imaginary components.\"\"\"\n",
        "        self.re = r\n",
        "        self.im = i\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "You can overload methods in structs and classes and overload module-level\n",
        "functions.\n",
        "\n",
        "Mojo doesn't support overloading solely on result type, and doesn't use result\n",
        "type or contextual type information for type inference, keeping things simple,\n",
        "fast, and predictable.  Mojo will never produce an \"expression too complex\"\n",
        "error, because its type-checker is simple and fast by definition.\n",
        "\n",
        "Again, if you leave your argument names without type definitions, then the\n",
        "function behaves just like Python with dynamic types. As soon as you define a\n",
        "single argument type, Mojo will look for overload candidates and resolve\n",
        "function calls as described above.\n",
        "\n",
        "Although we haven't discussed parameters yet (they're different from function\n",
        "arguments), you can also [overload functions and methods based on\n",
        "parameters](#overloading-on-parameters).\n",
        "\n",
        "### `fn` definitions\n",
        "\n",
        "The extensions above are the cornerstone that provides low-level programming\n",
        "and provide abstraction capabilities, but many systems programmers prefer more\n",
        "control and predictability than what `def` in Mojo provides. To recap, `def` is\n",
        "defined by necessity to be very dynamic, flexible and generally compatible with\n",
        "Python: arguments are mutable, local variables are implicitly declared on first\n",
        "use, and scoping isn't enforced. This is great for high level programming and\n",
        "scripting, but is not always great for systems programming. To complement this,\n",
        "Mojo provides an `fn` declaration which is like a \"strict mode\" for `def`.\n",
        "\n",
        "> Alternative: instead of using a new keyword like `fn`, we could instead add a\n",
        "modifier or decorator like `@strict def`. However, we need to take new keywords\n",
        "anyway and there is little cost to doing so. Also, in practice in systems\n",
        "programming domains, `fn` is used all the time so it probably makes sense to\n",
        "make it first class.\n",
        "\n",
        "As far as a caller is concerned, `fn` and `def` are interchangeable: there is\n",
        "nothing a `def` can provide that a `fn` cannot (and vice versa). The\n",
        "difference is that a `fn` is more limited and controlled on the *inside* of\n",
        "its body (alternatively: pedantic and strict). Specifically, `fn`s have a\n",
        "number of limitations compared to `def` functions:\n",
        "\n",
        "1. Argument values default to being immutable in the body of the function (like\n",
        "a `let`), instead of mutable (like a `var`). This catches accidental mutations,\n",
        "and permits the use of non-copyable types as arguments.\n",
        "\n",
        "2. Argument values require a type specification (except for `self` in a\n",
        "method), catching accidental omission of type specifications. Similarly, a\n",
        "missing return type specifier is interpreted as returning `None` instead of an\n",
        "unknown return type. Note that both can be explicitly declared to return\n",
        "`object`, which allows one to opt-in to the behavior of a `def` if desired.\n",
        "\n",
        "3. Implicit declaration of local variables is disabled, so all locals must be\n",
        "declared. This catches name typos and dovetails with the scoping provided by\n",
        "`let` and `var`.\n",
        "\n",
        "4. Both support raising exceptions, but this must be explicitly declared on a\n",
        "`fn` with the `raises` keyword.\n",
        "\n",
        "Programming patterns will vary widely across teams, and this level of\n",
        "strictness will not be for everyone. We expect that folks who are used to C++\n",
        "and already use MyPy-style type annotations in Python to prefer the use of\n",
        "`fn`s, but higher level programmers and ML researchers to continue to use\n",
        "`def`. Mojo allows you to freely intermix `def` and `fn` declarations, e.g.\n",
        "implementing some methods with one and others with the other, and allows each\n",
        "team or programmer to decide what is best for their use-case.\n",
        "\n",
        "For more about argument behavior in Mojo functions, see the section below about\n",
        "[Argument passing control and memory\n",
        "ownership](#argument-passing-control-and-memory-ownership)."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### The `__copyinit__` and `__moveinit__` special methods\n",
        "\n",
        "Mojo supports full \"value semantics\" as seen in languages like C++ and Swift,\n",
        "and it makes defining simple aggregates of fields very easy with the [`@value`\n",
        "decorator](#value-decorator).\n",
        "\n",
        "For advanced use cases, Mojo allows you to define custom constructors (using\n",
        "Python's existing `__init__` special method), custom destructors (using the\n",
        "existing `__del__` special method) and custom copy and move constructors using\n",
        "the `__copyinit__` and `__moveinit__` special methods.\n",
        "\n",
        "These low-level customization hooks can be useful when doing low level systems\n",
        "programming, e.g. with manual memory management.  For example, consider a\n",
        "dynamic string type that needs to allocate memory for the string data when\n",
        "constructed and destroy it when the value is destroyed:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [],
      "source": [
        "from memory.unsafe import Pointer\n",
        "\n",
        "struct HeapArray:\n",
        "    var data: Pointer[Int]\n",
        "    var size: Int\n",
        "\n",
        "    fn __init__(inout self, size: Int, val: Int):\n",
        "        self.size = size\n",
        "        self.data = Pointer[Int].alloc(self.size)\n",
        "        for i in range(self.size):\n",
        "            self.data[i] = val\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.data.free()\n",
        "\n",
        "    fn dump(self):\n",
        "        print(\"[\", end=\"\")\n",
        "        for i in range(self.size):\n",
        "            if i > 0:\n",
        "                print(\", \", end=\"\")\n",
        "            print(self.data.load(i), end=\"\")\n",
        "        print(\"]\")\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This array type is implemented using low level functions to show a simple\n",
        "example of how this works. However, if you try to copy an instance of\n",
        "`HeapArray` with the `=` operator, you might be surprised:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[1, 1, 1]\n",
            "[2, 2, 2, 2]\n",
            "[1, 1, 1]\n"
          ]
        }
      ],
      "source": [
        "var a = HeapArray(3, 1)\n",
        "a.dump()   # Should print [1, 1, 1]\n",
        "# Uncomment to see an error:\n",
        "# var b = a  # ERROR: Vector doesn't implement __copyinit__\n",
        "\n",
        "var b = HeapArray(4, 2)\n",
        "b.dump()   # Should print [2, 2, 2, 2]\n",
        "a.dump()   # Should print [1, 1, 1]\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you uncomment the line to copy `a` into `b`, you'll see that Mojo doesn't\n",
        "allow you to make a copy of our array: `HeapArray` contains an instance of\n",
        "`Pointer` (which is equivalent to a low-level C pointer), and Mojo doesn't know\n",
        "what kind of data it points to or how to copy it. More generally, some types\n",
        "(like atomic numbers) cannot be copied or moved around because their address\n",
        "provides an **identity** just like a class instance does.\n",
        "\n",
        "In this case, we do want our array to be copyable. To enable this, we have to\n",
        "implement the `__copyinit__` special method, which is conventionally\n",
        "implemented like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct HeapArray:\n",
        "    var data: Pointer[Int]\n",
        "    var size: Int\n",
        "\n",
        "    fn __init__(inout self, size: Int, val: Int):\n",
        "        self.size = size\n",
        "        self.data = Pointer[Int].alloc(self.size)\n",
        "        for i in range(self.size):\n",
        "            self.data[i] = val\n",
        "\n",
        "    fn __copyinit__(inout self, existing: Self):\n",
        "        self.size = existing.size\n",
        "        self.data = Pointer[Int].alloc(self.size)\n",
        "        for i in range(self.size):\n",
        "            self.data[i] = existing.data[i]\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.data.free()\n",
        "\n",
        "    fn dump(self):\n",
        "        print(\"[\", end=\"\")\n",
        "        for i in range(self.size):\n",
        "            if i > 0:\n",
        "                print(\", \", end=\"\")\n",
        "            print(self.data.load(i), end=\"\")\n",
        "        print(\"]\")\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "With this implementation, our code above works correctly and the `b = a` copy\n",
        "produces a logically distinct instance of the array with its own lifetime and\n",
        "data:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[1, 1, 1]\n",
            "[1, 1, 1]\n",
            "[1, 1, 1]\n"
          ]
        }
      ],
      "source": [
        "var a = HeapArray(3, 1)\n",
        "a.dump()   # Should print [1, 1, 1]\n",
        "# This is no longer an error:\n",
        "var b = a\n",
        "\n",
        "b.dump()   # Should print [1, 1, 1]\n",
        "a.dump()   # Should print [1, 1, 1]\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Mojo also supports the `__moveinit__` method which allows Rust-style\n",
        "moves (which transfers a value from one place to another when the source \n",
        "lifetime ends), and allows for defining custom move logic. For more detail, see\n",
        "the [Value Lifecycle](#value-lifecycle-birth-life-and-death-of-a-value)\n",
        "section below.\n",
        "\n",
        "Mojo provides full control over the lifetime of a value, including the ability\n",
        "to make types copyable, move-only, and not-movable. This is more control than\n",
        "languages like Swift and Rust offer, which require values to at least be\n",
        "movable. If you are curious how `existing` can be passed into the\n",
        "`__copyinit__` method without itself creating a copy, check out the section on\n",
        "[Borrowed arguments](#immutable-arguments-borrowed) below."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Argument passing control and memory ownership\n",
        "\n",
        "In both Python and Mojo, much of the language revolves around function calls: a\n",
        "lot of the (apparently) built-in behaviors are implemented in the standard\n",
        "library with \"dunder\" (double-underscore) methods. Inside these\n",
        "magic functions is where a lot of memory ownership is determined through\n",
        "argument passing.\n",
        "\n",
        "Let's review some details about how Python and Mojo pass arguments:\n",
        "\n",
        "- All values passed into a *Python* `def` function use reference semantics. This\n",
        "means the function can modify mutable objects passed into it and those changes\n",
        "are visible outside the function. However, the behavior is sometimes surprising\n",
        "for the uninitiated, because you can change the object that an argument points\n",
        "to and that change is not visible outside the function.\n",
        "\n",
        "- All values passed into a *Mojo* `def` function use value semantics by default.\n",
        "Compared to Python, this is an important difference: A Mojo `def` function\n",
        "receives a copy of all arguments—it can modify arguments inside the function,\n",
        "but the changes are **not** visible outside the function.\n",
        "\n",
        "- All values passed into a Mojo [`fn` function](#fn-definitions) are immutable\n",
        "references by default. This means the function can read the original object (it\n",
        "is *not* a copy), but it cannot modify the object at all.\n",
        "\n",
        "This convention for immutable argument passing in a Mojo `fn` is called\n",
        "\"borrowing.\" In the following sections, we'll explain how you can change the\n",
        "argument passing behavior in Mojo, for both `def` and `fn` functions.\n",
        "\n",
        "### Why argument conventions are important\n",
        "\n",
        "In Python, all fundamental values are references to objects—as described above,\n",
        "a Python function can modify the original object. Thus, Python developers are\n",
        "used to thinking about everything as reference semantic. However, at the\n",
        "CPython or machine level, you can see that the references themselves are\n",
        "actually passed *by-copy*—Python copies a pointer and adjusts reference counts.\n",
        "\n",
        "This Python approach provides a comfortable programming model for most people,\n",
        "but it requires all values to be heap-allocated (and results are occasionally\n",
        "surprising due to reference sharing). Mojo classes (TODO: will) follow\n",
        "the same reference-semantic approach for most objects, but this isn't practical\n",
        "for simple types like integers in a systems programming context. In these\n",
        "scenarios, we want the values to live on the stack or even in hardware\n",
        "registers. As such, Mojo structs are always inlined into their container,\n",
        "whether that be as the field of another type or into the stack frame of the\n",
        "containing function.\n",
        "\n",
        "This raises some interesting questions: How do you implement methods that need\n",
        "to mutate `self` of a structure type, such as `__iadd__`? How does `let` work,\n",
        "and how does it prevent mutation? How are the lifetimes of these values\n",
        "controlled to keep Mojo a memory-safe language?\n",
        "\n",
        "The answer is that the Mojo compiler uses dataflow analysis and type\n",
        "annotations to provide full control over value copies, aliasing of references,\n",
        "and mutation control. These features are similar in many ways to features in\n",
        "the Rust language, but they work somewhat differently in order to make\n",
        "Mojo easier to learn, and they integrate better into the Python ecosystem\n",
        "without requiring a massive annotation burden.\n",
        "\n",
        "In the following sections, you'll learn about how you can control memory\n",
        "ownership for objects passed into Mojo `fn` functions."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Immutable arguments (`borrowed`)\n",
        "\n",
        "A borrowed object is an **immutable reference** to an object that a function\n",
        "receives, instead of receiving a copy of the object. So the\n",
        "callee function has full read-and-execute access to the object, but it cannot\n",
        "modify it (the caller still has exclusive \"ownership\" of the object).\n",
        "\n",
        "For example, consider this struct that we don't want to copy when passing around\n",
        "instances of it:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Don't worry about this code yet. It's just needed for the function below.\n",
        "# It's a type so expensive to copy around so it does not have a\n",
        "# __copyinit__ method.\n",
        "struct SomethingBig:\n",
        "    var id_number: Int\n",
        "    var huge: HeapArray\n",
        "    fn __init__(inout self, id: Int):\n",
        "        self.huge = HeapArray(1000, 0)\n",
        "        self.id_number = id\n",
        "\n",
        "    # self is passed by-reference for mutation as described above.\n",
        "    fn set_id(inout self, number: Int):\n",
        "        self.id_number = number\n",
        "\n",
        "    # Arguments like self are passed as borrowed by default.\n",
        "    fn print_id(self):  # Same as: fn print_id(borrowed self):\n",
        "        print(self.id_number)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "When passing an instance of `SomethingBig` to a function, it's necessary to\n",
        "pass a reference because `SomethingBig` cannot be copied (it has no\n",
        "`__copyinit__` method). And, as mentioned above, `fn` arguments are immutable\n",
        "references by default, but you can explicitly define it with the `borrowed`\n",
        "keyword as shown in the `use_something_big()` function here:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "10\n",
            "20\n"
          ]
        }
      ],
      "source": [
        "fn use_something_big(borrowed a: SomethingBig, b: SomethingBig):\n",
        "    \"\"\"'a' and 'b' are both immutable, because 'borrowed' is the default.\"\"\"\n",
        "    a.print_id()\n",
        "    b.print_id()\n",
        "\n",
        "var a = SomethingBig(10)\n",
        "var b = SomethingBig(20)\n",
        "use_something_big(a, b)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This default applies to all arguments uniformly, including the `self` argument\n",
        "of methods. This is much more efficient when passing large values or when\n",
        "passing expensive values like a reference-counted pointer (which is the default\n",
        "for Python/Mojo classes), because the copy constructor and destructor don't\n",
        "have to be invoked when passing the argument. \n",
        "\n",
        "Because the default argument convention for `fn` functions is `borrowed`, Mojo\n",
        "has simple and logical code that does the right thing by default. For example,\n",
        "we don't want to copy or move all of `SomethingBig` just to invoke the\n",
        "`print_id()` method, or when calling `use_something_big()`.\n",
        "\n",
        "This borrowed argument convention is similar in some ways to passing an\n",
        "argument by `const&` in C++, which avoids a copy of the value and disables\n",
        "mutability in the callee. However, the borrowed convention differs from\n",
        "`const&` in C++ in two important ways:\n",
        "\n",
        "1. The Mojo compiler implements a borrow checker (similar to Rust) that\n",
        "prevents code from dynamically forming mutable references to a value when there\n",
        "are immutable references outstanding, and it prevents multiple mutable\n",
        "references to the same value. You are allowed to have multiple borrows (as the\n",
        "call to `use_something_big` does above) but you cannot pass something by mutable\n",
        "reference and borrow at the same time. (TODO: Not currently enabled).\n",
        "\n",
        "2. Small values like `Int`, `Float`, and `SIMD` are passed directly in machine\n",
        "registers instead of through an extra indirection (this is because they are\n",
        "declared with the [`@register_passable`\n",
        "decorator](#register_passable-struct-decorator)). This is a [significant\n",
        "performance\n",
        "enhancement](https://www.forrestthewoods.com/blog/should-small-rust-structs-be-passed-by-copy-or-by-borrow/)\n",
        "when compared to languages like C++ and Rust, and moves this optimization from\n",
        "every call site to being declarative on a type.\n",
        "\n",
        "Similar to Rust, Mojo's borrow checker enforces the exclusivity of invariants.\n",
        "The major difference between Rust and Mojo is that Mojo does not require a\n",
        "sigil on the caller side to pass by borrow. Also, Mojo is more efficient when\n",
        "passing small values, and Rust defaults to moving values instead of passing\n",
        "them around by borrow. These policy and syntax decisions allow Mojo to provide\n",
        "an easier-to-use programming model."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Mutable arguments (`inout`)\n",
        "\n",
        "On the other hand, if you define an `fn` function and want an argument to be\n",
        "mutable, you must declare the argument as mutable with the `inout` keyword.\n",
        "\n",
        "<div class=\"alert alert-block alert-success alert--success\">\n",
        "\n",
        "**Tip:** When you see `inout`, it means any changes made to the argument\n",
        "**in**side the function are visible **out**side the function.\n",
        "\n",
        "</div>\n",
        "\n",
        "Consider the following example, in which the `__iadd__` function (which\n",
        "implements the in-place add operation such as `x += 2`) tries to modify `self`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct MyInt:\n",
        "    var value: Int\n",
        "\n",
        "    fn __init__(inout self, v: Int):\n",
        "        self.value = v\n",
        "\n",
        "    fn __copyinit__(inout self, existing: MyInt):\n",
        "        self.value = existing.value\n",
        "\n",
        "    # self and rhs are both immutable in __add__.\n",
        "    fn __add__(self, rhs: MyInt) -> MyInt:\n",
        "        return MyInt(self.value + rhs.value)\n",
        "\n",
        "    # ... but this cannot work for __iadd__\n",
        "    # Uncomment to see the error:\n",
        "    #fn __iadd__(self, rhs: Int):\n",
        "    #    self = self + rhs  # ERROR: cannot assign to self!\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you uncomment the `__iadd__()` method, you'll get a compiler error.\n",
        "\n",
        "The problem here is that `self` is immutable because this is a Mojo `fn`\n",
        "function, so it can't change the internal state of the argument (the default\n",
        "argument convention is `borrowed`). The solution is to declare that the\n",
        "argument is mutable by adding the `inout` keyword on the `self` argument name:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct MyInt:\n",
        "    var value: Int\n",
        "\n",
        "    fn __init__(inout self, v: Int):\n",
        "        self.value = v\n",
        "\n",
        "    fn __copyinit__(inout self, existing: MyInt):\n",
        "        self.value = existing.value\n",
        "\n",
        "    # self and rhs are both immutable in __add__.\n",
        "    fn __add__(self, rhs: MyInt) -> MyInt:\n",
        "        return MyInt(self.value + rhs.value)\n",
        "\n",
        "    # ... now this works:\n",
        "    fn __iadd__(inout self, rhs: Int):\n",
        "        self = self + rhs\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now the `self` argument is mutable in the function and any changes are visible\n",
        "in the caller, so we can perform in-place addition with `MyInt`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "43\n"
          ]
        }
      ],
      "source": [
        "var x: MyInt = 42\n",
        "x += 1\n",
        "print(x.value) # prints 43 as expected\n",
        "\n",
        "# However...\n",
        "var y = x\n",
        "# Uncomment to see the error:\n",
        "# y += 1       # ERROR: Cannot mutate 'let' value\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you uncomment the last line above, mutation of the `let` value fails\n",
        "because it isn't possible to form a mutable reference to an immutable value\n",
        "(`let` makes the variable immutable).\n",
        "\n",
        "Of course, you can declare multiple `inout` arguments. For example, you can\n",
        "define and use a swap function like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "42 12\n",
            "12 42\n"
          ]
        }
      ],
      "source": [
        "fn swap(inout lhs: Int, inout rhs: Int):\n",
        "    var tmp = lhs\n",
        "    lhs = rhs\n",
        "    rhs = tmp\n",
        "\n",
        "var x = 42\n",
        "var y = 12\n",
        "print(x, y)  # Prints 42, 12\n",
        "swap(x, y)\n",
        "print(x, y)  # Prints 12, 42\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "A very important aspect of this system is that it all composes correctly."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-block alert-success alert--secondary\">\n",
        "\n",
        "Notice that we don't call this argument passing \"by reference.\" Although the\n",
        "`inout` convention is conceptually the same, we don't call it by-reference\n",
        "passing because the implementation may actually pass values using pointers.\n",
        "\n",
        "</div>"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Transfer arguments (`owned` and `^`)\n",
        "\n",
        "The final argument convention that Mojo supports is the `owned` argument\n",
        "convention. This convention is used for functions that want to take exclusive\n",
        "ownership over a value, and it is often used with the postfixed `^` operator.\n",
        "\n",
        "For example, imagine you're working with a move-only type like a unique\n",
        "pointer:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [],
      "source": [
        "# This is not really a unique pointer, we just model its behavior here\n",
        "# to serve the examples below.\n",
        "struct UniquePointer:\n",
        "    var ptr: Int\n",
        "\n",
        "    fn __init__(inout self, ptr: Int):\n",
        "        self.ptr = ptr\n",
        "\n",
        "    fn __moveinit__(inout self, owned existing: Self):\n",
        "        self.ptr = existing.ptr\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.ptr = 0\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "While the `borrow` convention makes it easy to work with this unique pointer\n",
        "without ceremony, at some point you might want to transfer ownership to some\n",
        "other function. This is a situation where you want to use the `^` \"transfer\"\n",
        "operator with your movable type.\n",
        "\n",
        "The `^` operator ends the lifetime of a value binding and transfers the value\n",
        "ownership to something else (in the following example, ownership is transferred\n",
        "to the `take_ptr()` function). To support this, you can define functions as\n",
        "taking `owned` arguments. For example, you can define `take_ptr()` to take\n",
        "ownership of an argument as follows:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "use_ptr\n",
            "100\n",
            "take_ptr\n",
            "100\n"
          ]
        }
      ],
      "source": [
        "fn take_ptr(owned p: UniquePointer):\n",
        "    print(\"take_ptr\")\n",
        "    print(p.ptr)\n",
        "\n",
        "fn use_ptr(borrowed p: UniquePointer):\n",
        "    print(\"use_ptr\")\n",
        "    print(p.ptr)\n",
        "\n",
        "fn work_with_unique_ptrs():\n",
        "    var p = UniquePointer(100)\n",
        "    use_ptr(p)    # Pass to borrowing function.\n",
        "    take_ptr(p^)  # Pass ownership of the `p` value to another function.\n",
        "\n",
        "    # Uncomment to see an error:\n",
        "    # use_ptr(p) # ERROR: p is no longer valid here!\n",
        "\n",
        "work_with_unique_ptrs()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Notice that if you uncomment the second call to `use_ptr()`, you get an error\n",
        "because the `p` value has been transferred to the `take_ptr()` function and,\n",
        "thus, the `p` value is destroyed.\n",
        "\n",
        "Because it is declared `owned`, the `take_ptr()` function knows it has unique\n",
        "access to the value.  This is very important for things like unique pointers,\n",
        "and it's useful when you want to avoid copies.\n",
        "\n",
        "For example, you will notably see the `owned` convention on destructors and on\n",
        "consuming move initializers. For example, our `HeapArray` struct defined\n",
        "earlier uses `owned` in its `__del__()` method, because you need to own a value\n",
        "to destroy it (or to steal its parts, in the case of a move constructor)."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Comparing `def` and `fn` argument passing\n",
        "\n",
        "Mojo's `def` function is essentially just sugaring for the `fn` function:\n",
        "\n",
        "- A `def` argument without an explicit type annotation defaults to `Object`.\n",
        "\n",
        "- A `def` argument without a convention keyword (such as `inout` or `owned`) is\n",
        "passed by implicit copy into a mutable var with the same name as the argument.\n",
        "(This requires that the type have a `__copyinit__` method.)\n",
        "\n",
        "For example, these two functions have the same behavior:\n",
        "\n",
        "```mojo\n",
        "def example(inout a: Int, b: Int, c):\n",
        "    # b and c use value semantics so they're mutable in the function\n",
        "    ...\n",
        "\n",
        "fn example(inout a: Int, b_in: Int, c_in: Object):\n",
        "    # b_in and c_in are immutable references, so we make mutable shadow copies\n",
        "    var b = b_in\n",
        "    var c = c_in\n",
        "    ...\n",
        "```\n",
        "\n",
        "The shadow copies typically add no overhead, because references for small types\n",
        "like `Object` are cheap to copy. The expensive part is adjusting the reference\n",
        "count, but that's eliminated by a move optimization."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Python integration\n",
        "\n",
        "It's easy to use Python modules you know and love in Mojo. You can import\n",
        "any Python module into your Mojo program and create Python types from Mojo\n",
        "types.\n",
        "\n",
        "### Importing Python modules\n",
        "\n",
        "To import a Python module in Mojo, just call `Python.import_module()` with the\n",
        "module name:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [],
      "source": [
        "from python import Python\n",
        "\n",
        "fn use_array() raises:\n",
        "    # This is equivalent to Python's `import numpy as np`\n",
        "    var np = Python.import_module(\"numpy\")\n",
        "\n",
        "    # Now use numpy as if writing in Python\n",
        "    var array = np.array([1, 2, 3])\n",
        "    print(array)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[1 2 3]\n"
          ]
        }
      ],
      "source": [
        "use_array()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Yes, this imports Python NumPy, and you can import *any other Python module* you \n",
        "have installed.\n",
        "\n",
        "A few things to note:\n",
        "\n",
        "- Currently, you cannot import individual members (such as a single Python class\n",
        "  or function)—you must import the whole Python module and then access members\n",
        "  through the module name.\n",
        "\n",
        "- Mojo doesn't yet support top-level code, so the `import_module()` call must\n",
        "  be inside another method. This means you may need to import a module multiple\n",
        "  times or pass around a reference to the module.\n",
        "\n",
        "- `import_module()` may raise an exception (for example, if the module isn't\n",
        "  installed). If you're using it inside a `fn` function, you need to either\n",
        "  handle errors (using a `try/except` clause), or add the `raises` keyword to\n",
        "  the function signature. You'll also see this when calling Python functions\n",
        "  that may raise exceptions. (Raising exceptions is much more common in Python\n",
        "  code than in the Mojo standard library, which \n",
        "  [limits their use for performance reasons](/mojo/roadmap.html#the-standard-library-has-limited-exceptions-use).)\n",
        "\n",
        "### Mojo types in Python\n",
        "\n",
        "Mojo primitive types implicitly convert into Python objects.\n",
        "Today we support lists, tuples, integers, floats, booleans, and strings.\n",
        "\n",
        "For example, given this Python function that prints Python types:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [],
      "source": [
        "%%python\n",
        "def type_printer(my_list, my_tuple, my_int, my_string, my_float):\n",
        "    print(type(my_list))\n",
        "    print(type(my_tuple))\n",
        "    print(type(my_int))\n",
        "    print(type(my_string))\n",
        "    print(type(my_float))\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You can pass the Python function Mojo types with no problem:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "<class 'list'>\n",
            "<class 'tuple'>\n",
            "<class 'int'>\n",
            "<class 'str'>\n",
            "<class 'float'>\n"
          ]
        }
      ],
      "source": [
        "type_printer([0, 3], (False, True), 4, \"orange\", 3.4)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Notice that in a Jupyter notebook, the Python function declared above is\n",
        "automatically available to any Mojo code in following code cells.\n",
        "\n",
        "Mojo doesn't have a standard Dictionary yet, so it is not yet possible\n",
        "to create a Python dictionary from a Mojo dictionary. You can work with\n",
        "Python dictionaries in Mojo though! To create a Python dictionary, use the\n",
        "[`dict`](/mojo/stdlib/python/python.html#dict) method:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [],
      "source": [
        "from python import Python\n",
        "from python.object import PythonObject\n",
        "\n",
        "fn use_dict() raises:\n",
        "    var dictionary = Python.dict()\n",
        "    dictionary[\"fruit\"] = \"apple\"\n",
        "    dictionary[\"starch\"] = \"potato\"\n",
        "\n",
        "    var keys: PythonObject = [\"fruit\", \"starch\", \"protein\"]\n",
        "    var N: Int = keys.__len__().__index__()\n",
        "    print(N, \"items\")\n",
        "\n",
        "    for i in range(N):\n",
        "        if Python.is_type(dictionary.get(keys[i]), Python.none()):\n",
        "            print(keys[i], \"is not in dictionary\")\n",
        "        else:\n",
        "            print(keys[i], \"is included\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Then call the `use_dict()` function to see the results:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3 items\n",
            "fruit is included\n",
            "starch is included\n",
            "protein is not in dictionary\n"
          ]
        }
      ],
      "source": [
        "use_dict()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Importing local Python modules\n",
        "\n",
        "If you have some local Python code you want to use in Mojo, just add\n",
        "the directory to the Python path and then import the module.\n",
        "\n",
        "For example, suppose you have a Python file named `mypython.py`:\n",
        "\n",
        "```python\n",
        "import numpy as np\n",
        "\n",
        "def my_algorithm(a, b):\n",
        "    array_a = np.random.rand(a, a)\n",
        "    return array_a + b\n",
        "```\n",
        "\n",
        "Here's how you can import it and use it in a Mojo file:\n",
        "\n",
        "```mojo\n",
        "from python import Python\n",
        "\n",
        "fn use_my_module() raises:\n",
        "    Python.add_to_path(\"path/to/module\")\n",
        "    var mypython = Python.import_module(\"mypython\")\n",
        "\n",
        "    var c = mypython.my_algorithm(2, 3)\n",
        "    print(c)\n",
        "```\n",
        "\n",
        "There's no need to worry about memory management when using Python in Mojo.\n",
        "Everything just works because Mojo was designed for Python from the beginning."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Parameterization: compile-time metaprogramming\n",
        "\n",
        "One of Python's most amazing features is its extensible runtime\n",
        "metaprogramming features. This has enabled a wide range of libraries and\n",
        "provides a flexible and extensible programming model that Python programmers\n",
        "everywhere benefit from. Unfortunately, these features also come at a cost:\n",
        "because they are evaluated at runtime, they directly impact run-time efficiency\n",
        "of the underlying code. Because they are not known to the IDE, it is difficult\n",
        "for IDE features like code completion to understand them and use them to\n",
        "improve the developer experience.\n",
        "\n",
        "Outside the Python ecosystem, static metaprogramming is also an important part\n",
        "of development, enabling the development of new programming paradigms and\n",
        "advanced libraries. There are many examples of prior art in this space, with\n",
        "different tradeoffs, for example:\n",
        "\n",
        "1. Preprocessors (e.g. C preprocessor, Lex/YACC, etc) are perhaps the heaviest\n",
        "handed. They are fully general but the worst in terms of developer experience\n",
        "and tools integration.\n",
        "\n",
        "2. Some languages (like Lisp and Rust) support (sometimes \"hygienic\") macro\n",
        "expansion features, enabling syntactic extension and boilerplate reduction with\n",
        "somewhat better tooling integration.\n",
        "\n",
        "3. Some older languages like C++ have very large and complex metaprogramming\n",
        "languages (templates) that are a dual to the *runtime* language. These are\n",
        "notably difficult to learn and have poor compile times and error messages.\n",
        "\n",
        "4. Some languages (like Swift) build many features into the core language in a\n",
        "first-class way to provide good ergonomics for common cases at the expense of\n",
        "generality.\n",
        "\n",
        "5. Some newer languages like Zig integrate a language interpreter into the\n",
        "compilation flow, and allow the interpreter to reflect over the AST as it is\n",
        "compiled. This allows many of the same features as a macro system with better\n",
        "extensibility and generality.\n",
        "\n",
        "For Modular's work in AI, high-performance machine learning kernels, and\n",
        "accelerators, we need high abstraction capabilities provided by advanced\n",
        "metaprogramming systems. We needed high-level zero-cost abstractions,\n",
        "expressive libraries, and large-scale integration of multiple variants of\n",
        "algorithms. We want library developers to be able to extend the system, just\n",
        "like they do in Python, providing an extensible developer platform.\n",
        "\n",
        "That said, we are not willing to sacrifice developer experience (including\n",
        "compile times and error messages) nor are we interested in building a parallel\n",
        "language ecosystem that is difficult to teach. We can learn from these previous\n",
        "systems but also have new technologies to build on top of, including MLIR and\n",
        "fine-grained language-integrated caching technologies.\n",
        "\n",
        "As such, Mojo supports compile-time metaprogramming built\n",
        "into the compiler as a separate stage of compilation—after parsing, semantic\n",
        "analysis, and IR generation, but before lowering to target-specific code. It\n",
        "uses the same host language for runtime programs as it does for metaprograms,\n",
        "and leverages MLIR to represent and evaluate these programs predictably.\n",
        "\n",
        "Let's take a look at some simple examples.\n",
        "\n",
        "<div class=\"alert alert-block alert-success alert--secondary\">\n",
        "\n",
        "**About \"parameters\":** Python developers use the words \"arguments\" and\n",
        "\"parameters\" fairly interchangeably for \"things that are passed into\n",
        "functions.\" We decided to reclaim \"parameter\" and \"parameter expression\" to\n",
        "represent a compile-time value in Mojo, and continue to use \"argument\" and\n",
        "\"expression\" to refer to runtime values. This allows us to align around words\n",
        "like \"parameterized\" and \"parametric\" for compile-time metaprogramming.\n",
        "\n",
        "</div>"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Defining parameterized types and functions\n",
        "\n",
        "You can parameterize structs and functions by specifying parameter names and\n",
        "types in square brackets (using an extended version of the [PEP695\n",
        "syntax](https://peps.python.org/pep-0695/)). Unlike argument values, parameter\n",
        "values are known at compile-time, which enables an additional level of\n",
        "abstraction and code reuse, plus compiler optimizations such as\n",
        "[autotuning](#autotuning-adaptive-compilation).\n",
        "\n",
        "For instance, let's look at a\n",
        "[SIMD](https://en.wikipedia.org/wiki/Single_instruction,_multiple_data) type,\n",
        "which represents a low-level vector register in hardware that holds multiple\n",
        "instances of a scalar data-type. Hardware accelerators are constantly\n",
        "introducing new vector data types, and even CPUs may have 512-bit or longer SIMD\n",
        "vectors. In order to access the SIMD instructions on these processors, the data\n",
        "must be shaped into the proper SIMD width (data type) and length (vector size).\n",
        "\n",
        "However, it's not feasible to define all the different SIMD variations with\n",
        "Mojo's built-in types. So, Mojo's `SIMD` type (defined as a struct) exposes the\n",
        "common SIMD operations in its methods, and makes the SIMD data type and size\n",
        "values parametric. This allows you to directly map your data to the SIMD vectors\n",
        "on any hardware. \n",
        "\n",
        "Here is a cut-down (non-functional) version of Mojo's `SIMD` type definition:\n",
        "\n",
        "```mojo\n",
        "struct SIMD[type: DType, size: Int]:\n",
        "    var value: … # Some low-level MLIR stuff here\n",
        "\n",
        "    # Create a new SIMD from a number of scalars\n",
        "    fn __init__(inout self, *elems: Scalar[type]):  ...\n",
        "\n",
        "    # Fill a SIMD with a duplicated scalar value.\n",
        "    @staticmethod\n",
        "    fn splat(x: Scalar[type]) -> SIMD[type, size]: ...\n",
        "\n",
        "    # Cast the elements of the SIMD to a different elt type.\n",
        "    fn cast[target: DType](self) -> SIMD[target, size]: ...\n",
        "\n",
        "    # Many standard operators are supported.\n",
        "    fn __add__(self, rhs: Self) -> Self: ...\n",
        "```\n",
        "\n",
        "Defining each SIMD variant with parameters is great for code reuse because the\n",
        "`SIMD` type can express all the different vector variants statically, instead of\n",
        "requiring the language to pre-define every variant.\n",
        "\n",
        "Because `SIMD` is a parameterized type, the `self` argument in its functions\n",
        "carries those parameters—the full type name is `SIMD[type, size]`. Although\n",
        "it's valid to write this out (as shown in the return type of `splat()`), this\n",
        "can be verbose, so we recommend using the `Self` type (from\n",
        "[PEP673](https://peps.python.org/pep-0673/)) like the `__add__` example does."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Overloading on parameters\n",
        "\n",
        "Functions and methods can be overloaded on their parameter signatures. The\n",
        "overload resolution logic filters for candidates according to the following\n",
        "rules, in order of precedence:\n",
        "\n",
        "1) Candidates with the minimal number of implicit conversions (in both arguments\n",
        "and parameters).\n",
        "2) Candidates without variadic arguments.\n",
        "3) Candidates without variadic parameters.\n",
        "4) Candidates with the shortest parameter signature.\n",
        "5) Non-`@staticmethod` candidates (over `@staticmethod` ones, if available). \n",
        "\n",
        "If there is more than one candidate after applying these rules, the overload\n",
        "resolution fails. For example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "foo[x: MyInt, a: Int]()\n",
            "bar[a: Int](b: Int)\n",
            "bar[*a: Int](b: Int)\n"
          ]
        }
      ],
      "source": [
        "@register_passable(\"trivial\")\n",
        "struct MyInt:\n",
        "    \"\"\"A type that is implicitly convertible to `Int`.\"\"\"\n",
        "    var value: Int\n",
        "\n",
        "    @always_inline(\"nodebug\")\n",
        "    fn __init__(_a: Int) -> Self:\n",
        "        return Self {value: _a}\n",
        "\n",
        "fn foo[x: MyInt, a: Int]():\n",
        "    print(\"foo[x: MyInt, a: Int]()\")\n",
        "\n",
        "fn foo[x: MyInt, y: MyInt]():\n",
        "    print(\"foo[x: MyInt, y: MyInt]()\")\n",
        "\n",
        "fn bar[a: Int](b: Int):\n",
        "    print(\"bar[a: Int](b: Int)\")\n",
        "\n",
        "fn bar[a: Int](*b: Int):\n",
        "    print(\"bar[a: Int](*b: Int)\")\n",
        "\n",
        "fn bar[*a: Int](b: Int):\n",
        "    print(\"bar[*a: Int](b: Int)\")\n",
        "\n",
        "fn parameter_overloads[a: Int, b: Int, x: MyInt]():\n",
        "    # `foo[x: MyInt, a: Int]()` is called because it requires no implicit\n",
        "    # conversions, whereas `foo[x: MyInt, y: MyInt]()` requires one.\n",
        "    foo[x, a]()\n",
        "\n",
        "    # `bar[a: Int](b: Int)` is called because it does not have variadic\n",
        "    # arguments or parameters.\n",
        "    bar[a](b)\n",
        "\n",
        "    # `bar[*a: Int](b: Int)` is called because it has variadic parameters.\n",
        "    bar[a, a, a](b)\n",
        "\n",
        "parameter_overloads[1, 2, MyInt(3)]()\n",
        "\n",
        "struct MyStruct:\n",
        "    fn __init__(inout self):\n",
        "        pass\n",
        "\n",
        "    fn foo(inout self):\n",
        "        print(\"calling instance menthod\")\n",
        "\n",
        "    @staticmethod\n",
        "    fn foo():\n",
        "        print(\"calling static menthod\")\n",
        "\n",
        "fn test_static_overload():\n",
        "    var a = MyStruct()\n",
        "    # `foo(inout self)` takes precedence over a static method.\n",
        "    a.foo()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Using parameterized types and functions\n",
        "\n",
        "You can instantiate parametric types and functions by passing values to the\n",
        "parameters in square brackets. For example, for the `SIMD` type above, `type`\n",
        "specifies the data type and `size` specifies the length of the SIMD vector (it\n",
        "must be a power of 2):"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "small_vec type: float32 length: 4\n",
            "bigger_vec2 type: float32 length: 32\n"
          ]
        }
      ],
      "source": [
        "# Make a vector of 4 floats.\n",
        "var small_vec = SIMD[DType.float32, 4](1.0, 2.0, 3.0, 4.0)\n",
        "\n",
        "# Make a big vector containing 1.0 in float16 format.\n",
        "var big_vec = SIMD[DType.float16, 32].splat(1.0)\n",
        "\n",
        "# Do some math and convert the elements to float32.\n",
        "var bigger_vec = (big_vec+big_vec).cast[DType.float32]()\n",
        "\n",
        "# You can write types out explicitly if you want of course.\n",
        "var bigger_vec2 : SIMD[DType.float32, 32] = bigger_vec\n",
        "\n",
        "print('small_vec type:', small_vec.element_type, 'length:', len(small_vec))\n",
        "print('bigger_vec2 type:', bigger_vec2.element_type, 'length:', len(bigger_vec2))\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note that the `cast()` method also needs a parameter to specify the type you\n",
        "want from the cast (the method definition above expects a `target` parametric\n",
        "value). Thus, just like how the `SIMD` struct is a generic type definition, the\n",
        "`cast()` method is a generic method definition that gets instantiated at\n",
        "compile-time instead of runtime, based on the parameter value.\n",
        "\n",
        "The code above shows the use of concrete types (that is, it\n",
        "instantiates `SIMD` using known type values), but the major power of parameters\n",
        "comes from the ability to define parametric algorithms and types (code that\n",
        "uses the parameter values). For example, here's how to define a parametric\n",
        "algorithm with `SIMD` that is type- and width-agnostic:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[0.154296875, 0.154296875, 0.154296875, 0.154296875]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "from math import sqrt\n",
        "\n",
        "fn rsqrt[dt: DType, width: Int](x: SIMD[dt, width]) -> SIMD[dt, width]:\n",
        "    return 1 / sqrt(x)\n",
        "\n",
        "print(rsqrt[DType.float16, 4](42))\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Notice that the `x` argument is actually a `SIMD` type based on the function\n",
        "parameters. The runtime program can use the value of parameters, because the\n",
        "parameters are resolved at compile-time before they are needed by the runtime\n",
        "program (but compile-time parameter expressions cannot use runtime values).\n",
        "\n",
        "The Mojo compiler is also smart about type inference with parameters. Note\n",
        "that the above function is able to call the parametric\n",
        "[`sqrt[]()`](https://docs.modular.com/mojo/stdlib/math/math.html#sqrt) function\n",
        "without specifying the parameters—the compiler infers its parameters based on\n",
        "the parametric `x` value passed into it, as if you\n",
        "wrote `sqrt[dt, width](x)` explicitly. Also note that `rsqrt()` chose to\n",
        "define its first parameter named `width` even though the `SIMD` type names it\n",
        "`size`, and there is no problem."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Optional parameters and keyword parameters\n",
        "\n",
        "Just as you can specify [optional arguments](/mojo/manual/basics/#optional-arguments)\n",
        "in function signatures, you can also define an optional _parameter_ by \n",
        "giving it a default value. You can also pass parameters by keyword.\n",
        "For a function or struct with multiple optional parameters, using keywords\n",
        "allows you to pass only the parameters you want to specify, regardless of\n",
        "their position in the function signature. \n",
        "\n",
        "For example, here's a function with two parameters, each with a default value:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn speak[a: Int = 3, msg: StringLiteral = \"woof\"]():\n",
        "    print(msg, a)\n",
        "\n",
        "fn use_defaults() raises:\n",
        "    speak()             # prints 'woof 3'\n",
        "    speak[5]()          # prints 'woof 5'\n",
        "    speak[7, \"meow\"]()  # prints 'meow 7'\n",
        "    speak[msg=\"baaa\"]() # prints 'baaa 3'\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Recall that Mojo can infer parameter values in a parametric function, based on\n",
        "the parametric values attached to an argument value (see the `rsqrt[]()`\n",
        "example above). If the parametric function also has a default value defined,\n",
        "then the inferred parameter type takes precedence.\n",
        "\n",
        "For example, in the following code, we update the parametric `speak[]()` function\n",
        "to take an argument with a parametric type. Although the function has a default\n",
        "parameter value for `a`, Mojo instead uses the inferred `a` parameter value\n",
        "from the `bar` argument (as written, the default `a` value can never be used,\n",
        "but this is just for demonstration purposes):"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {},
      "outputs": [],
      "source": [
        "@value\n",
        "struct Bar[v: Int]:\n",
        "    pass\n",
        "\n",
        "fn foo[a: Int = 3, msg: StringLiteral = \"woof\"](bar: Bar[a]):\n",
        "    print(msg, a)\n",
        "\n",
        "fn use_inferred():\n",
        "    foo(Bar[9]())  # prints 'woof 9'\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "As mentioned above, you can also use optional parameters and keyword \n",
        "parameters in a struct:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct KwParamStruct[greeting: String = \"Hello\", name: String = \"🔥mojo🔥\"]:\n",
        "    fn __init__(inout self):\n",
        "        print(greeting, name)\n",
        "\n",
        "fn use_kw_params():\n",
        "    var a = KwParamStruct[]()                 # prints 'Hello 🔥mojo🔥'\n",
        "    var b = KwParamStruct[name=\"World\"]()     # prints 'Hello World'\n",
        "    var c = KwParamStruct[greeting=\"Hola\"]()  # prints 'Hola 🔥mojo🔥'\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-block alert-info alert--secondary\">\n",
        "\n",
        "**Note:** Mojo currently includes only partial support for keyword parameters, so\n",
        "some features such as keyword-only parameters and variadic keyword parameters \n",
        "(for example, `**kwparams`) are not supported yet.\n",
        "\n",
        "</div>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "### Automatic parameterization of functions\n",
        "\n",
        "Mojo  supports \"automatic\" parameterization of functions. If a \n",
        "function argument type is parametric but the function signature\n",
        "*doesn't* specify the parameters, they are automatically added as \n",
        "input parameters on the function. This is easier to understand\n",
        "with an example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn print_params(vec: SIMD):\n",
        "    print(vec.type)\n",
        "    print(vec.size)\n",
        "\n",
        "fn main():\n",
        "    var v = SIMD[DType.float64, 4](1.0, 2.0, 3.0, 4.0)\n",
        "    print_params(v)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In the above example, the `print_params` function is automatically \n",
        "parameterized. It takes a parameterized type (`SIMD`), but doesn't specify \n",
        "parameter values for it. Instead, it treats the types' parameters as its own, as\n",
        "if you had written them explicitly:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn print_params[type: DType, size: Int](vec: SIMD[type, size]):\n",
        "    print(vec.type)\n",
        "    print(vec.size)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "When you pass `print_params()` a concrete instance of the `SIMD` type, it can \n",
        "access the original input parameters as attributes on the instance (for example,\n",
        "`vec.type`). This is necessary for an automatically parameterized\n",
        "function, since it doesn't have any other way to access the parameters. But it \n",
        "actually works in any context. You can access the input parameters of a \n",
        "parameterized type as attributes on the type:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn main():\n",
        "    print(SIMD[DType.float32, 2].size) # prints 2\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Or as attributes on an _instance_ of the type:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn main():\n",
        "    var x = SIMD[DType.int32, 2](4, 8)\n",
        "    print(x.type) # prints int32\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Parameter expressions are just Mojo code\n",
        "\n",
        "A parameter expression is any code expression (such as `a+b`) that occurs where\n",
        "a parameter is expected. Parameter expressions support operators and function\n",
        "calls, just like runtime code, and all parameter types use the same type\n",
        "system as the runtime program (such as `Int` and `DType`).\n",
        "\n",
        "Because parameter expressions use the same grammar and types as runtime\n",
        "Mojo code, you can use many \"dependent type\" features. For example, you might\n",
        "want to define a helper function to concatenate two SIMD vectors:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "result type: float32 length: 4\n"
          ]
        }
      ],
      "source": [
        "fn concat[ty: DType, len1: Int, len2: Int](\n",
        "        lhs: SIMD[ty, len1], rhs: SIMD[ty, len2]) -> SIMD[ty, len1+len2]:\n",
        "\n",
        "    var result = SIMD[ty, len1 + len2]()\n",
        "    for i in range(len1):\n",
        "        result[i] = SIMD[ty, 1](lhs[i])\n",
        "    for j in range(len2):\n",
        "        result[len1 + j] = SIMD[ty, 1](rhs[j])\n",
        "    return result\n",
        "\n",
        "var a = SIMD[DType.float32, 2](1, 2)\n",
        "var x = concat[DType.float32, 2, 2](a, a)\n",
        "\n",
        "print('result type:', x.element_type, 'length:', len(x))\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note how the resulting length is the sum of the input vector lengths, and you\n",
        "can express that with a simple `+` operation. For a more complex example, take\n",
        "a look at the [`SIMD.shuffle()`](https://docs.modular.com/mojo/MojoStdlib/SIMD.html#shuffle) method in\n",
        "the standard library: it takes two input SIMD values, a vector shuffle mask as\n",
        "a list, and returns a SIMD that matches the length of the shuffle mask.\n",
        "\n",
        "### Powerful compile-time programming\n",
        "\n",
        "While simple expressions are useful, sometimes you want to write imperative\n",
        "compile-time logic with control flow. For example, the `isclose()` function in\n",
        "the Mojo `Math` module uses exact equality for integers but \"close\" comparison\n",
        "for floating-point. You can even do compile-time recursion. For instance, here\n",
        "is an example \"tree reduction\" algorithm that sums all elements of a vector\n",
        "recursively into a scalar:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[1, 2, 3, 4]\n",
            "Elements sum: 10\n"
          ]
        }
      ],
      "source": [
        "fn slice[ty: DType, new_size: Int, size: Int](\n",
        "        x: SIMD[ty, size], offset: Int) -> SIMD[ty, new_size]:\n",
        "    var result = SIMD[ty, new_size]()\n",
        "    for i in range(new_size):\n",
        "        result[i] = SIMD[ty, 1](x[i + offset])\n",
        "    return result\n",
        "\n",
        "fn reduce_add[ty: DType, size: Int](x: SIMD[ty, size]) -> Int:\n",
        "    @parameter\n",
        "    if size == 1:\n",
        "        return int(x[0])\n",
        "    elif size == 2:\n",
        "        return int(x[0]) + int(x[1])\n",
        "\n",
        "    # Extract the top/bottom halves, add them, sum the elements.\n",
        "    alias half_size = size // 2\n",
        "    var lhs = slice[ty, half_size, size](x, 0)\n",
        "    var rhs = slice[ty, half_size, size](x, half_size)\n",
        "    return reduce_add[ty, half_size](lhs + rhs)\n",
        "\n",
        "var x = SIMD[DType.index, 4](1, 2, 3, 4)\n",
        "print(x)\n",
        "print(\"Elements sum:\", reduce_add[DType.index, 4](x))\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This makes use of the `@parameter if` feature, which is an `if` statement that\n",
        "runs at compile-time. It requires that its condition be a valid parameter\n",
        "expression, and ensures that only the live branch of the `if` statement is\n",
        "compiled into the program.\n",
        "\n",
        "### Mojo types are just parameter expressions\n",
        "\n",
        "While we've shown how you can use parameter expressions within types, type\n",
        "annotations can themselves be arbitrary expressions (just like in Python).\n",
        "Types in Mojo have a special metatype type, allowing type-parametric algorithms\n",
        "and functions to be defined. \n",
        "\n",
        "For example, we can create a simplified `Array` that supports arbitrary types of\n",
        "the elements (via the `AnyRegType` parameter):"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3.1400001049041748 3.1400001049041748 3.1400001049041748 3.1400001049041748\n"
          ]
        }
      ],
      "source": [
        "struct Array[T: AnyRegType]:\n",
        "    var data: Pointer[T]\n",
        "    var size: Int\n",
        "\n",
        "    fn __init__(inout self, size: Int, value: T):\n",
        "        self.size = size\n",
        "        self.data = Pointer[T].alloc(self.size)\n",
        "        for i in range(self.size):\n",
        "            self.data[i] = value\n",
        "\n",
        "    fn __getitem__(self, i: Int) -> T:\n",
        "        return self.data[i]\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.data.free()\n",
        "\n",
        "var v = Array[Float32](4, 3.14)\n",
        "print(v[0], v[1], v[2], v[3])\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Notice that the `T` parameter is being used as the formal type for the\n",
        "`value` arguments and the return type of the `__getitem__` function. Parameters\n",
        "allow the `Array` type to provide different APIs based on the different\n",
        "use-cases. \n",
        "\n",
        "There are many other cases that benefit from more advanced use of parameters.\n",
        "For example, you can execute a closure N times in parallel, feeding in a value\n",
        "from the context, like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn parallelize[func: fn (Int) -> None](num_work_items: Int):\n",
        "    # Not actually parallel: see the 'algorithm' module for real implementation.\n",
        "    for i in range(num_work_items):\n",
        "        func(i)\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Another example where this is important is with variadic generics, where an\n",
        "algorithm or data structure may need to be defined over a list of heterogeneous\n",
        "types such as for a tuple:\n",
        "\n",
        "```mojo\n",
        "struct Tuple[*Ts: AnyRegType]:\n",
        "    var _storage : *Ts\n",
        "```\n",
        "\n",
        "And although we don't have enough metatype helpers in place yet, we should be\n",
        "able to write something like this in the future (though overloading is still a\n",
        "better way to handle this):\n",
        "\n",
        "```mojo\n",
        "struct Array[T: AnyRegType]:\n",
        "    fn __getitem__[IndexType: AnyRegType](self, idx: IndexType)\n",
        "       -> (ArraySlice[T] if issubclass(IndexType, Range) else T):\n",
        "       ...\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### `alias`: named parameter expressions\n",
        "\n",
        "It is very common to want to *name* compile-time values. Whereas `var` defines a\n",
        "runtime value, and `let` defines a runtime constant, we need a way to define a\n",
        "compile-time temporary value. For this, Mojo uses an `alias` declaration. \n",
        "\n",
        "For example, the `DType` struct implements a simple enum using aliases for the\n",
        "enumerators like this (the actual `DType` implementation details vary a bit):\n",
        "\n",
        "```mojo\n",
        "struct DType:\n",
        "    var value : UI8\n",
        "    alias invalid = DType(0)\n",
        "    alias bool = DType(1)\n",
        "    alias int8 = DType(2)\n",
        "    alias uint8 = DType(3)\n",
        "    alias int16 = DType(4)\n",
        "    alias int16 = DType(5)\n",
        "    ...\n",
        "    alias float32 = DType(15)\n",
        "```\n",
        "\n",
        "This allows clients to use `DType.float32` as a parameter expression (which also\n",
        "works as a runtime value) naturally. Note that this is invoking the\n",
        "runtime constructor for `DType` at compile-time.\n",
        "\n",
        "Types are another common use for alias. Because types are compile-time\n",
        "expressions, it is handy to be able to do things like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "metadata": {},
      "outputs": [],
      "source": [
        "alias Float16 = SIMD[DType.float16, 1]\n",
        "alias UInt8 = SIMD[DType.uint8, 1]\n",
        "\n",
        "var x : Float16   # FLoat16 works like a \"typedef\"\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Like `var` and `let`, aliases obey scope, and you can use local aliases within\n",
        "functions as you'd expect.\n",
        "\n",
        "By the way, both `None` and `AnyRegType` are defined as [type\n",
        "aliases](https://docs.modular.com/mojo/MojoBuiltin/TypeAliases.html)."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## \"Value Lifecycle\": Birth, life and death of a value\n",
        "\n",
        "At this point, you should understand the core semantics and features for Mojo\n",
        "functions and types, so we can now discuss how they fit together to express\n",
        "new types in Mojo.\n",
        "\n",
        "Many existing languages express design points with different tradeoffs: C++, for\n",
        "example, is very powerful but often accused of\n",
        "\"getting the defaults wrong\" which leads to bugs and mis-features.  Swift is\n",
        "easy to work with, but has a less predictable model that copies values a lot and\n",
        "is dependent on an \"ARC optimizer\" for performance. Rust started with strong\n",
        "value ownership goals to satisfy its borrow checker, but relies on values being\n",
        "movable, which makes it challenging to express custom move constructors and\n",
        "can put a lot of stress on `memcpy` performance. In Python, everything is a\n",
        "reference to a class, so it never really faces issues with types.\n",
        "\n",
        "For Mojo, we've learned from these existing systems, and we aim to\n",
        "provide a model that's very powerful while still easy to learn and understand.\n",
        "We also don't want to require \"best effort\" and difficult-to-predict\n",
        "optimization passes built into a \"sufficiently smart\" compiler.\n",
        "\n",
        "To explore these issues, we look at different value classifications and the\n",
        "relevant Mojo features that go into expressing them, and build from the\n",
        "bottom-up. We use C++ as the primary comparison point in examples because it is\n",
        "widely known, but we occasionally reference other languages if they provide a\n",
        "better comparison point.\n",
        "\n",
        "### Types that cannot be instantiated\n",
        "\n",
        "The most bare-bones type in Mojo is one that doesn't allow you to create\n",
        "instances of it: these types have no initializer at all, and if they have a\n",
        "destructor, it will never be invoked (because there cannot be instances to\n",
        "destroy):"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct NoInstances:\n",
        "    var state: Int  # Pretty useless\n",
        "\n",
        "    alias my_int = Int\n",
        "\n",
        "    @staticmethod\n",
        "    fn print_hello():\n",
        "        print(\"hello world\")\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Mojo types do not get default constructors, move constructors, member-wise\n",
        "initializers or anything else by default, so it is impossible to create an\n",
        "instance of this `NoInstances` type.  In order to get them, you need to define\n",
        "an `__init__` method or use a decorator that synthesizes an initializer.  As\n",
        "shown, these types can be useful as \"namespaces\" because you can refer to\n",
        "static members like `NoInstances.my_int` or `NoInstances.print_hello()` even\n",
        "though you cannot instantiate an instance of the type.\n",
        "\n",
        "### Non-movable and non-copyable types\n",
        "\n",
        "If we take a step up the ladder of sophistication, we’ll get to types that can\n",
        "be instantiated, but once they are pinned to an address in memory, they cannot\n",
        "be implicitly moved or copied.  This can be useful to implement types like\n",
        "atomic operations (such as `std::atomic` in C++) or other types where the memory\n",
        "address of the value is its identity and is critical to its purpose:"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "```mojo\n",
        "struct Atomic:\n",
        "    var state: Int\n",
        "\n",
        "    fn __init__(inout self, state: Int = 0):\n",
        "        self.state = state\n",
        "\n",
        "    fn __iadd__(inout self, rhs: Int):\n",
        "        #...atomic magic...\n",
        "\n",
        "    fn get_value(self) -> Int:\n",
        "        return atomic_load_int(self.state)\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This class defines an initializer but no copy or move constructors, so once it\n",
        "is initialized it can never be moved or copied.  This is safe and useful because\n",
        "Mojo's ownership system is fully \"address correct\" - when this is initialized\n",
        "onto the stack or in the field of some other type, it never needs to move.\n",
        "\n",
        "Note that Mojo’s approach controls only the built-in move operations, such as\n",
        "`a = b` copies and the [`^` transfer operator](#owned-arguments). One\n",
        "useful pattern you can use for your own types (like `Atomic` above) is to add\n",
        "an explicit `copy()` method (a non-\"dunder\" method). This can be useful to make\n",
        "explicit copies of an instance when it is known safe to the programmer."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Unique \"move-only\" types\n",
        "\n",
        "If we take one more step up the ladder of capabilities, we will encounter types\n",
        "that are \"unique\" - there are many examples of this in C++, such as types like\n",
        "`std::unique_ptr` or even a `FileDescriptor` type that owns an underlying POSIX\n",
        "file descriptor. These types are pervasive in languages like Rust, where\n",
        "copying is discouraged, but \"move\" is free. In Mojo, you can implement these\n",
        "kinds of moves by defining the `__moveinit__` method to take ownership of a\n",
        "unique type. For example:"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "```mojo\n",
        "# This is a simple wrapper around POSIX-style fcntl.h functions.\n",
        "struct FileDescriptor:\n",
        "    var fd: Int\n",
        "\n",
        "    # This is how we move our unique type.\n",
        "    fn __moveinit__(inout self, owned existing: Self):\n",
        "        self.fd = existing.fd\n",
        "\n",
        "    # This takes ownership of a POSIX file descriptor.\n",
        "    fn __init__(inout self, fd: Int):\n",
        "        self.fd = fd\n",
        "\n",
        "    fn __init__(inout self, path: String):\n",
        "        # Error handling omitted, call the open(2) syscall.\n",
        "        self = FileDescriptor(open(path, ...))\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        close(self.fd)   # pseudo code, call close(2)\n",
        "\n",
        "    fn dup(self) -> Self:\n",
        "        # Invoke the dup(2) system call.\n",
        "        return Self(dup(self.fd))\n",
        "    fn read(...): ...\n",
        "    fn write(...): ...\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The consuming move constructor (`__moveinit__`) takes ownership of an existing\n",
        "`FileDescriptor`, and moves its internal implementation details over to a new\n",
        "instance.  This is because instances of `FileDescriptor` may exist at different\n",
        "locations, and they can be logically moved around—stealing the body of one\n",
        "value and moving it into another.\n",
        "\n",
        "Here is an egregious example that will invoke `__moveinit__` multiple times:"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "```mojo\n",
        "fn egregious_moves(owned fd1: FileDescriptor):\n",
        "    # fd1 and fd2 have different addresses in memory, but the\n",
        "    # transfer operator moves unique ownership from fd1 to fd2.\n",
        "    var fd2 = fd1^\n",
        "\n",
        "    # Do it again, a use of fd2 after this point will produce an error.\n",
        "    var fd3 = fd2^\n",
        "\n",
        "    # We can do this all day...\n",
        "    var fd4 = fd3^\n",
        "    fd4.read(...)\n",
        "    # fd4.__del__() runs here\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note how ownership of the value is transferred between various values that own\n",
        "it, using the postfix-`^` \"transfer\" operator, which destroys a previous\n",
        "binding and transfer ownership to a new constant. If you are familiar with C++,\n",
        "the simple way to think about the transfer operator is like `std::move`, but in\n",
        "this case, we can see that it is able to move things without resetting them to\n",
        "a state that can be destroyed: in C++, if your move operator failed to change\n",
        "the old value’s `fd` instance, it would get closed twice.\n",
        "\n",
        "Mojo tracks the liveness of values and allows you to define custom move\n",
        "constructors. This is rarely needed, but extremely powerful when it is. For\n",
        "example, some types like the [`llvm::SmallVector\n",
        "type`](https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h)\n",
        "use the \"inline storage\" optimization technique, and they may want to be\n",
        "implemented with an \"inner pointer\" into their instance. This is a well-known\n",
        "trick to reduce pressure on the malloc memory allocator, but it means that a\n",
        "\"move\" operation needs custom logic to update the pointer when that happens.\n",
        "\n",
        "With Mojo, this is as simple as implementing a custom `__moveinit__` method.\n",
        "This is something that is also easy to implement in C++ (though, with\n",
        "boilerplate in the cases where you don’t need custom logic) but is difficult to\n",
        "implement in other popular memory-safe languages.\n",
        "\n",
        "One additional note is that while the Mojo compiler provides good predictability\n",
        "and control, it is also very sophisticated.  It reserves the right to eliminate\n",
        "temporaries and the corresponding copy/move operations.  If this is\n",
        "inappropriate for your type, you should use explicit methods like `copy()`\n",
        "instead of the dunder methods."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Copyable types\n",
        "\n",
        "The next step up from movable types are copyable types.  Copyable types are\n",
        "also very common - programmers generally expect things like strings and arrays\n",
        "to be copyable, and every Python Object reference is copyable - by copying the\n",
        "pointer and adjusting the reference count.\n",
        "\n",
        "There are many ways to implement copyable types.  One can implement reference\n",
        "semantic types like Python or Java, where you propagate shared pointers around,\n",
        "one can use immutable data structures that are easily shareable because they are\n",
        "never mutated once created, and one can implement deep value semantics through\n",
        "lazy copy-on-write as Swift does.  Each of these approaches has different\n",
        "tradeoffs, and Mojo takes the opinion that while we want a few common sets of\n",
        "collection types, we can also support a wide range of specialized ones that\n",
        "focus on particular use cases.\n",
        "\n",
        "In Mojo, you can do this by implementing the `__copyinit__` method.  Here is an\n",
        "example of that using a simple `String` (in pseudo-code):"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "```mojo\n",
        "struct MyString:\n",
        "    var data: Pointer[UI8]\n",
        "\n",
        "    # StringRef is a pointer + length and works with StringLiteral.\n",
        "    def __init__(inout self, input: StringRef):\n",
        "        self.data = ...\n",
        "\n",
        "    # Copy the string by deep copying the underlying malloc'd data.\n",
        "    def __copyinit__(inout self, existing: Self):\n",
        "        self.data = strdup(existing.data)\n",
        "\n",
        "    # This isn't required, but optimizes unneeded copies.\n",
        "    def __moveinit__(inout self, owned existing: Self):\n",
        "        self.data = existing.data\n",
        "\n",
        "    def __del__(owned self):\n",
        "        free(self.data.address)\n",
        "\n",
        "    def __add__(self, rhs: MyString) -> MyString: ...\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This simple type is a pointer to a \"null-terminated\" string data allocated with\n",
        "malloc, using old-school C APIs for clarity. It implements the `__copyinit__`,\n",
        "which maintains the invariant that each instance of `MyString` owns its\n",
        "underlying pointer and frees it upon destruction. This implementation builds on\n",
        "tricks we’ve seen above, and implements a `__moveinit__` constructor, which\n",
        "allows it to completely eliminate temporary copies in some common cases. You\n",
        "can see this behavior in this code sequence:"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "```mojo\n",
        "fn test_my_string():\n",
        "    var s1 = MyString(\"hello \")\n",
        "\n",
        "    var s2 = s1    # s2.__copyinit__(s1) runs here\n",
        "\n",
        "    print(s1)\n",
        "\n",
        "    var s3 = s1^   # s3.__moveinit__(s1) runs here\n",
        "\n",
        "    print(s2)\n",
        "    # s2.__del__() runs here\n",
        "    print(s3)\n",
        "    # s3.__del__() runs here\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In this case, you can see both why a copy constructor is needed: without one,\n",
        "the duplication of the `s1` value into `s2` would be an error - because you\n",
        "cannot have two live instances of the same non-copyable type. The move\n",
        "constructor is optional but helps the assignment into `s3`: without it, the\n",
        "compiler would invoke the copy constructor from s1, then destroy the old `s1`\n",
        "instance. This is logically correct but introduces extra runtime overhead.\n",
        "\n",
        "Mojo destroys values eagerly, which allows it to transform\n",
        "copy+destroy pairs into single move operations, which can lead to much better\n",
        "performance than C++ without requiring the need for pervasive micromanagement\n",
        "of `std::move`."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Trivial types\n",
        "\n",
        "The most flexible types are ones that are just \"bags of bits\".  These types are\n",
        "\"trivial\" because they can be copied, moved, and destroyed without invoking\n",
        "custom code.  Types like these are arguably the most common basic type that\n",
        "surrounds us: things like integers and floating point values are all trivial.\n",
        "From a language perspective, Mojo doesn’t need special support for these, it\n",
        "would be perfectly fine for type authors to implement these things as no-ops,\n",
        "and allow the inliner to just make them go away.\n",
        "\n",
        "There are two reasons that approach would be suboptimal: one is that we don’t\n",
        "want the boilerplate of having to define a bunch of methods on trivial types,\n",
        "and second, we don’t want the compile-time overhead of generating and pushing\n",
        "around a bunch of function calls, only to have them inline away to nothing.\n",
        "Furthermore, there is an orthogonal concern, which is that many of these types\n",
        "are trivial in another way: they are tiny, and should be passed around in the\n",
        "registers of a CPU, not indirectly in memory.\n",
        "\n",
        "As such, Mojo provides a struct decorator that solves all of these problems.\n",
        "You can implement a type with the `@register_passable(\"trivial\")` decorator,\n",
        "and this tells Mojo that the type should be copyable and movable but that it\n",
        "has no user-defined logic for doing this.  It also tells Mojo to prefer to pass\n",
        "the value in CPU registers, which can lead to efficiency benefits.\n",
        "\n",
        "TODO: This decorator is due for reconsideration.  Lack of custom logic\n",
        "copy/move/destroy logic and \"passability in a register\" are orthogonal concerns\n",
        "and should be split.  This former logic should be subsumed into a more general\n",
        "`@value(\"trivial\")` decorator, which is orthogonal from `@register_passable`."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### `@value` decorator\n",
        "\n",
        "Mojo's [value lifecycle](#value-lifecycle-birth-life-and-death-of-a-value) provides simple and predictable\n",
        "hooks that give you the ability to express exotic low-level things like\n",
        "`Atomic` correctly. This is great for control and for a simple programming\n",
        "model, but most structs are simple aggregations of other types,\n",
        "and we don't want to write a lot of boilerplate for them. To solve\n",
        "this, Mojo provides a `@value` decorator for structs that synthesizes a lot of\n",
        "boilerplate for you.\n",
        "\n",
        "You can think of `@value` as an extension of Python's\n",
        "[`@dataclass`](https://docs.python.org/3/library/dataclasses.html) that also\n",
        "handles Mojo's `__moveinit__` and `__copyinit__` methods.\n",
        "\n",
        "The `@value` decorator takes a look at the fields of your type, and generates\n",
        "some members that are missing. For example, consider a simple struct like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "metadata": {},
      "outputs": [],
      "source": [
        "@value\n",
        "struct MyPet:\n",
        "    var name: String\n",
        "    var age: Int\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Mojo will notice that you do not have a member-wise initializer, a move\n",
        "constructor, or a copy constructor, and it will synthesize these for you as if\n",
        "you had written:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 41,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct MyPet:\n",
        "    var name: String\n",
        "    var age: Int\n",
        "\n",
        "    fn __init__(inout self, owned name: String, age: Int):\n",
        "        self.name = name^\n",
        "        self.age = age\n",
        "\n",
        "    fn __copyinit__(inout self, existing: Self):\n",
        "        self.name = existing.name\n",
        "        self.age = existing.age\n",
        "\n",
        "    fn __moveinit__(inout self, owned existing: Self):\n",
        "        self.name = existing.name^\n",
        "        self.age = existing.age\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "When you add the `@value` decorator, Mojo synthesizes each of these special\n",
        "methods only when it doesn't exist. You can override the behavior of one or\n",
        "more by defining your own version. For example, it is fairly common to want a\n",
        "custom copy constructor but use the default member-wise and move constructor.\n",
        "\n",
        "The arguments to`__init__` are all passed as `owned` arguments since the struct\n",
        "takes ownership and stores the value.  This is a useful micro-optimization and\n",
        "enables the use of move-only types.  Trivial types like `Int` are also passed\n",
        "as owned values, but since that doesn't mean anything for them, we elide the\n",
        "marker and the transfer operator (`^`) for clarity.\n",
        "\n",
        "<div class=\"alert alert-block alert-success alert--secondary\">\n",
        "\n",
        "**Note:** If your type contains any [move-only](#unique-move-only-types)\n",
        "fields, Mojo will not generate a copy constructor because it cannot copy those\n",
        "fields.  Further, the `@value` decorator only works on types whose members are\n",
        "copyable and/or movable.  If you have something like `Atomic` in your struct,\n",
        "then it probably isn't a value type, and you don't want these members anyway.\n",
        "\n",
        "Also notice that the `MyPet` struct above doesn't include the `__del__()`\n",
        "destructor—Mojo also synthesizes this, but it doesn't require the `@value`\n",
        "decorator (see the section below about [destructors](#behavior-of-destructors)).\n",
        "\n",
        "</div>\n",
        "\n",
        "There is no way to suppress the generation of specific methods or customize\n",
        "generation at this time, but we can add arguments to the `@value` generator to\n",
        "do this if there is demand."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Behavior of destructors\n",
        "\n",
        "Any struct in Mojo can have a destructor (a `__del__()` method), which is\n",
        "automatically run when the value's lifetime ends (typically the point at which\n",
        "the value is last used). For example, a simple string might look like this (in\n",
        "pseudo code):\n",
        "\n",
        "```mojo\n",
        "@value\n",
        "struct MyString:\n",
        "    var data: Pointer[UInt8]\n",
        "\n",
        "    def __init__(inout self, input: StringRef): ...\n",
        "    def __add__(self, rhs: String) -> MyString: ...\n",
        "    def __del__(owned self):\n",
        "        free(self.data.address)\n",
        "```\n",
        "\n",
        "Mojo destroys values like `MyString` (it calls the `__del__()` destructor)\n",
        "using an **\"As Soon As Possible\"** (ASAP) policy that runs after every call.\n",
        "Mojo does *not* wait until the end of the code block to destroy unused values.\n",
        "Even in an expression like `a+b+c+d`, Mojo destroys the intermediate\n",
        "expressions eagerly, as soon as they are no longer needed—it does not wait\n",
        "until the end of the statement.\n",
        "\n",
        "The Mojo compiler automatically invokes the destructor when a value is dead\n",
        "and provides strong guarantees about when the destructor is run. Mojo uses\n",
        "static compiler analysis to reason about your code and decide when to insert\n",
        "calls to the destructor. For example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 42,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "hello a\n",
            "hello b\n",
            "final a\n"
          ]
        }
      ],
      "source": [
        "fn use_strings():\n",
        "    var a = String(\"hello a\")\n",
        "    var b = String(\"hello b\")\n",
        "    print(a)\n",
        "    # a.__del__() runs here for \"hello a\"\n",
        "\n",
        "\n",
        "    print(b)\n",
        "    # b.__del__() runs here\n",
        "\n",
        "    a = String(\"temporary a\")\n",
        "    # a.__del__() runs here because \"temporary a\" is never used\n",
        "\n",
        "    # Other stuff happens here\n",
        "\n",
        "    a = String(\"final a\")\n",
        "    print(a)\n",
        "    # a.__del__() runs again here for \"final a\"\n",
        "\n",
        "use_strings()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In the code above, you’ll see that the `a` and `b` values are created early on,\n",
        "and each initialization of a value is matched with a call to a destructor.\n",
        "Notice that `a` is destroyed multiple times—once for each time it receives a\n",
        "new value.\n",
        "\n",
        "Now, this might be surprising to a C++ programmer, because it's different from\n",
        "the [RAII pattern](https://en.cppreference.com/w/cpp/language/raii) in which\n",
        "C++ destroys values at the end of a scope. Mojo also follows the principle\n",
        "that values acquire resources in a constructor and release resources in a\n",
        "destructor, but eager destruction in Mojo has a number of strong advantages\n",
        "over scope-based destruction in C++:\n",
        "\n",
        "- The Mojo approach eliminates the need for types to implement re-assignment\n",
        "  operators, like `operator=(const T&)` and `operator=(T&&)` in C++, making it\n",
        "  easier to define types and eliminating a concept.\n",
        "\n",
        "- Mojo does not allow mutable references to overlap with other mutable\n",
        "  references or with immutable borrows. One major way that it provides a\n",
        "  predictable programming model is by making sure that references to objects die\n",
        "  as soon as possible, avoiding confusing situations where the compiler thinks a\n",
        "  value could still be alive and interfere with another value, but that isn’t\n",
        "  clear to the user.\n",
        "\n",
        "- Destroying values at last-use composes nicely with \"move\" optimization, which\n",
        "  transforms a \"copy+del\" pair into a \"move\" operation, a generalization of\n",
        "  C++ move optimizations like NRVO (named return value optimization).\n",
        "\n",
        "- Destroying values at end-of-scope in C++ is problematic for some common\n",
        "  patterns like tail recursion because the destructor calls happen after the\n",
        "  tail call. This can be a significant performance and memory problem for\n",
        "  certain functional programming patterns.\n",
        "\n",
        "Importantly, Mojo's eager destruction also works well within Python-style `def`\n",
        "functions to provide destruction guarantees (without a garbage collector) at a\n",
        "fine-grain level—recall that Python doesn’t really provide scopes beyond a\n",
        "function, so C++-style destruction in Mojo would be a lot less useful.\n",
        "\n",
        "<div class=\"alert alert-block alert-success alert--secondary\">\n",
        "\n",
        "**Note:** Mojo also supports the Python-style [`with`\n",
        "statement](https://docs.python.org/3/reference/compound_stmts.html#the-with-statement),\n",
        "which provides more deliberately-scoped access to resources.\n",
        "\n",
        "</div>\n",
        "\n",
        "The Mojo approach is more similar to how Rust and Swift work, because they both\n",
        "have strong value ownership tracking and provide memory safety.  One difference\n",
        "is that their implementations require the use of a [dynamic \"drop\n",
        "flag\"](https://doc.rust-lang.org/nomicon/drop-flags.html)—they maintain hidden\n",
        "shadow variables to keep track of the state of your values to provide safety.\n",
        "These are often optimized away, but the Mojo approach eliminates this overhead\n",
        "entirely, making the generated code faster and avoiding ambiguity."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Field-sensitive lifetime management\n",
        "\n",
        "In addition to Mojo’s lifetime analysis being fully control-flow aware, it is\n",
        "also fully field-sensitive (each field of a structure is tracked\n",
        "independently). That is, Mojo separately keeps track of whether a \"whole\n",
        "object\" is fully or only partially initialized/destroyed.\n",
        "\n",
        "For example, consider this code:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 43,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "foo\n",
            "hello\n"
          ]
        }
      ],
      "source": [
        "@value\n",
        "struct TwoStrings:\n",
        "    var str1: String\n",
        "    var str2: String\n",
        "\n",
        "fn use_two_strings():\n",
        "    var ts = TwoStrings(\"foo\", \"bar\")\n",
        "    print(ts.str1)\n",
        "    # ts.str1.__del__() runs here\n",
        "\n",
        "    # Other stuff happens here\n",
        "\n",
        "    ts.str1 = String(\"hello\") # Overwrite ts.str1\n",
        "    print(ts.str1)\n",
        "    # ts.__del__() runs here\n",
        "\n",
        "use_two_strings()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note that the `ts.str1` field is destroyed almost immediately,\n",
        "because Mojo knows that it will be overwritten down below.  You can also see\n",
        "this when using the [transfer operator](#owned-arguments), for example:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 44,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "hello\n"
          ]
        }
      ],
      "source": [
        "fn consume(owned arg: String):\n",
        "    pass\n",
        "\n",
        "fn use(arg: TwoStrings):\n",
        "    print(arg.str1)\n",
        "\n",
        "fn consume_and_use_two_strings():\n",
        "    var ts = TwoStrings(\"foo\", \"bar\")\n",
        "    consume(ts.str1^)\n",
        "    # ts.str1.__moveinit__() runs here\n",
        "\n",
        "    # ts is now only partially initialized here!\n",
        "\n",
        "    ts.str1 = String(\"hello\")  # All together now\n",
        "    use(ts)                    # This is ok\n",
        "    # ts.__del__() runs here\n",
        "\n",
        "consume_and_use_two_strings()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Notice that the code transfers ownership of the `str1` field: for the duration\n",
        "of `other_stuff()`, the `str1` field is completely uninitialized because\n",
        "ownership was transferred to `consume()`. Then\n",
        "`str1` is reinitialized before it is used by the `use()` function (if it\n",
        "weren’t, Mojo would reject the code with an uninitialized field error).\n",
        "\n",
        "Mojo's rule on this is powerful and intentionally straight-forward: fields can\n",
        "be temporarily transferred, but the \"whole object\" must be constructed with the\n",
        "aggregate type’s initializer and destroyed with the aggregate destructor. This\n",
        "means that it isn’t possible to create an object by initializing only its\n",
        "fields, nor is it possible to tear down an object by destroying only its\n",
        "fields. For example, this code does not compile:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 45,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn consume_and_use_two_strings():\n",
        "    var ts = TwoStrings(\"foo\", \"bar\") # ts is initialized\n",
        "    # Uncomment to see an error:\n",
        "    # consume(ts.str1^)\n",
        "    # Because `ts` is not used anymore, it should be destroyed here, but\n",
        "    # the object is not whole, preventing the overall value from being destroyed\n",
        "\n",
        "    var ts2 : TwoStrings # ts2 type is declared but not initialized\n",
        "    ts2.str1 = String(\"foo\")\n",
        "    ts2.str2 = String(\"bar\")  # Both the member are initialized\n",
        "    # Uncomment to see an error:\n",
        "    # use(ts2) # Error: 'ts2' isn't fully initialized\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "While we could allow patterns like this to happen, we reject this because a\n",
        "value is more than a sum of its parts.  Consider a `FileDescriptor` that\n",
        "contains a POSIX file descriptor as an integer value: there is a\n",
        "big difference between destroying the integer (a no-op) and destroying the\n",
        "`FileDescriptor` (it might call the `close()` system call).  Because of this, we\n",
        "require all full-value initialization to go through initializers and be\n",
        "destroyed with their full-value destructor.\n",
        "\n",
        "For what it's worth, Mojo does internally have an equivalent of the Rust\n",
        "[`mem::forget`](https://doc.rust-lang.org/std/mem/fn.forget.html) function,\n",
        "which explicitly disables a destructor and has a corresponding internal feature\n",
        "for \"blessing\" an object, but they aren’t exposed for user consumption at this\n",
        "point."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Field lifetimes in `__init__`\n",
        "\n",
        "The behavior of an `__init__` method works almost like any other method—there\n",
        "is a small bit of magic: it knows that the fields of an object\n",
        "are uninitialized, but it believes the full object is initialized.  This means\n",
        "that you can use `self` as a whole object as soon as all the fields are\n",
        "initialized:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "metadata": {},
      "outputs": [],
      "source": [
        "fn use(arg: TwoStrings2):\n",
        "    pass\n",
        "\n",
        "struct TwoStrings2:\n",
        "    var str1: String\n",
        "    var str2: String\n",
        "\n",
        "    fn __init__(inout self, cond: Bool, other: String):\n",
        "        self.str1 = String()\n",
        "        if cond:\n",
        "            self.str2 = other\n",
        "            use(self)  # Safe to use immediately!\n",
        "            # self.str2.__del__(): destroyed because overwritten below.\n",
        "\n",
        "        self.str2 = self.str1\n",
        "        use(self)  # Safe to use immediately!\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "Similarly, it's safe for initializers in Mojo to completely\n",
        "overwrite `self`, such as by delegating to other initializers:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 47,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct TwoStrings3:\n",
        "    var str1: String\n",
        "    var str2: String\n",
        "\n",
        "    fn __init__(inout self):\n",
        "        self.str1 = String()\n",
        "        self.str2 = String()\n",
        "\n",
        "    fn __init__(inout self, one: String):\n",
        "        self = TwoStrings3()  # Delegate to the basic init\n",
        "        self.str1 = one\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Field lifetimes of `owned` arguments in `__moveinit__` and `__del__` \n",
        "\n",
        "A final bit of magic exists for the `owned` arguments of a `__moveinit__()` move\n",
        "initializer and a `__del__()` destructor. To recap, these method signatures look\n",
        "like this:\n",
        "\n",
        "```mojo\n",
        "struct TwoStrings:\n",
        "    ...\n",
        "    fn __moveinit__(inout self, owned existing: Self):\n",
        "        # Initializes a new `self` by consuming the contents of `existing`\n",
        "    fn __del__(owned self):\n",
        "        # Destroys all resources in `self`\n",
        "```\n",
        "\n",
        "These methods face an interesting but obscure problem: both methods are in\n",
        "charge of dismantling the `owned` `existing`/`self` value. That is,\n",
        "`__moveinit__()` destroys sub-elements of `existing` in order to transfer\n",
        "ownership to a new instance, while `__del__()` implements the deletion logic\n",
        "for its `self`. As such, they both want to own and transform elements of the\n",
        "`owned` value, and they definitely don’t want the `owned` value's destructor to\n",
        "also run (in the case of the `__del__()` method, that would turn into an\n",
        "infinite loop).\n",
        "\n",
        "To solve this problem, Mojo handles these two methods specially by assuming\n",
        "that their whole values are destroyed upon reaching any return from the method.\n",
        "This means that the whole object may be used before the field values are\n",
        "transferred. For example, this works as you expect:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 48,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "str1: foo\n",
            "str2: bar\n",
            "Consumed foo\n"
          ]
        }
      ],
      "source": [
        "fn consume(owned str: String):\n",
        "    print('Consumed', str)\n",
        "\n",
        "struct TwoStrings4:\n",
        "    var str1: String\n",
        "    var str2: String\n",
        "\n",
        "    fn __init__(inout self, one: String):\n",
        "        self.str1 = one\n",
        "        self.str2 = String(\"bar\")\n",
        "\n",
        "    fn __moveinit__(inout self, owned existing: Self):\n",
        "        self.str1 = existing.str1\n",
        "        self.str2 = existing.str2\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.dump() # Self is still whole here\n",
        "        # Mojo calls self.str2.__del__() since str2 isn't used anymore\n",
        "\n",
        "        consume(self.str1^)\n",
        "        # str1 has now been transferred;\n",
        "        # `self.__del__()` is not called (avoiding an infinite loop).\n",
        "\n",
        "    fn dump(inout self):\n",
        "        print('str1:', self.str1)\n",
        "        print('str2:', self.str2)\n",
        "\n",
        "fn use_two_strings():\n",
        "    var two_strings = TwoStrings4(\"foo\")\n",
        "\n",
        "# We use a function call to ensure the `two_strings` ownership is enforced\n",
        "# (Currently, ownership is not enforced for top-level code in notebooks)\n",
        "use_two_strings()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You should not generally have to think about this, but if you have logic with\n",
        "inner pointers into members, you may need to keep them alive for some logic\n",
        "within the destructor or move initializer itself.  You can do this by assigning\n",
        "to the `_` \"discard\" pattern:\n",
        "\n",
        "```mojo\n",
        "fn __del__(owned self):\n",
        "    self.dump() # Self is still whole here\n",
        "\n",
        "    consume(self.str1^)\n",
        "    _ = self.str2\n",
        "    # self.str2.__del__(): Mojo destroys str2 after its last use.\n",
        "```"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In this case, if `consume()` implicitly refers to some value in `str2` somehow,\n",
        "this will ensure that `str2` isn’t destroyed until the last use when it is\n",
        "accessed by the `_` discard pattern."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Defining the `__del__` destructor\n",
        "\n",
        "You should define the `__del__()` method to perform any kind of cleanup the\n",
        "type requires. Usually, that includes freeing memory for any fields that are\n",
        "not trivial or destructible—Mojo automatically destroys any trivial and\n",
        "destructible types as soon as they're not used anymore.\n",
        "\n",
        "For example, consider this struct:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct MyPet:\n",
        "    var name: String\n",
        "    var age: Int\n",
        "\n",
        "    fn __init__(inout self, owned name: String, age: Int):\n",
        "        self.name = name^\n",
        "        self.age = age\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "There's no need to define the `__del__()` method because `String` is a\n",
        "destructible (it has its own `__del__()` method) and Mojo destroys it as soon\n",
        "as it's no longer used (which is exactly when the `MyPet` instance is no longer\n",
        "used), and `Int` is a [trivial type](#trivial-types) and Mojo reclaims this\n",
        "memory also as soon as possible (although a little differently, without need\n",
        "for a `__del__()` method).\n",
        "\n",
        "Whereas, the following struct must define the `__del__()` method to free\n",
        "the memory allocated for its `Pointer`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "metadata": {},
      "outputs": [],
      "source": [
        "struct Array[Type: AnyRegType]:\n",
        "    var data: Pointer[Type]\n",
        "    var size: Int\n",
        "\n",
        "    fn __init__(inout self, size: Int, value: Type):\n",
        "        self.size = size\n",
        "        self.data = Pointer[Type].alloc(self.size)\n",
        "        for i in range(self.size):\n",
        "            self.data[i] = value\n",
        "\n",
        "    fn __del__(owned self):\n",
        "        self.data.free()\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Lifetimes\n",
        "\n",
        "TODO: Explain how returning references work, tied into lifetimes which dovetail\n",
        "with parameters.  This is not enabled yet.\n",
        "\n",
        "## Type traits\n",
        "\n",
        "This is a feature very much like Rust traits or Swift protocols or Haskell type\n",
        "classes. Note, this is not implemented yet."
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Advanced/Obscure Mojo features\n",
        "\n",
        "This section describes power-user features that are important for building the\n",
        "bottom-est level of the standard library. This level of the stack is inhabited\n",
        "by narrow features that require experience with compiler internals to\n",
        "understand and utilize effectively.\n",
        "\n",
        "### `@register_passable` struct decorator\n",
        "\n",
        "The default model for working with values is\n",
        "they live in memory, so they have an identity, which means they are passed\n",
        "indirectly to and from functions (equivalently, they are passed \"by reference\"\n",
        "at the machine level). This is great for types that cannot be moved, and is a\n",
        "safe default for large objects or things with expensive copy operations.\n",
        "However, it is inefficient for tiny things like a single integer or\n",
        "floating point number.\n",
        "\n",
        "To solve this, Mojo allows structs to opt-in to being passed in a register\n",
        "instead of passing through memory with the `@register_passable` decorator.\n",
        "You'll see this decorator on types like `Int` in the standard library:\n",
        "\n",
        "```mojo\n",
        "@register_passable(\"trivial\")\n",
        "struct Int:\n",
        "    var value: __mlir_type.`!pop.scalar<index>`\n",
        "\n",
        "    fn __init__(value: __mlir_type.`!pop.scalar<index>`) -> Self:\n",
        "        return Self {value: value}\n",
        "    ...\n",
        "```\n",
        "\n",
        "The basic `@register_passable` decorator does not change the fundamental\n",
        "behavior of a type: it still needs to have a `__copyinit__` method to be\n",
        "copyable, may still have a `__init__` and `__del__` methods, etc. The major\n",
        "effect of this decorator is on\n",
        "internal implementation details: `@register_passable` types are typically\n",
        "passed in machine registers (subject to the details of the underlying\n",
        "architecture).\n",
        "\n",
        "There are only a few observable effects of this decorator to the typical Mojo\n",
        "programmer:\n",
        "\n",
        "1. `@register_passable` types are not able to hold instances of types\n",
        "that are not themselves `@register_passable`.\n",
        "\n",
        "2. Instances of `@register_passable` types do not have predictable identity,\n",
        "and so the `self` pointer is not stable/predictable (e.g. in hash tables).\n",
        "\n",
        "3. `@register_passable` arguments and result are exposed to C and C++ directly,\n",
        "instead of being passed by-pointer.\n",
        "\n",
        "4. The `__init__` and `__copyinit__` methods of this type are implicitly static\n",
        "(like `__new__` in Python) and return their results by-value instead of taking\n",
        "`inout self`.\n",
        "\n",
        "We expect that this decorator will be used pervasively on core standard library\n",
        "types, but is safe to ignore for general application level code.\n",
        "\n",
        "The `Int` example above actually uses the \"trivial\" variant of this decorator.\n",
        "It changes the passing convention as described above but also disallows copy\n",
        "and move constructors and destructors (synthesizing them all trivially).\n",
        "\n",
        "> TODO: Trivial needs to be decoupled to its own decorator since it applies to\n",
        "memory types as well.\n",
        "\n",
        "<!--\n",
        "TOWRITE: Each builtin decorator should be mentioned. Eventually, decorators\n",
        "should appear in the API docs.\n",
        "\n",
        "> TODO: We need to decide how to namespace these, should these go into a 'mojo'\n",
        "package or something?\n",
        "-->\n",
        "\n",
        "### `@always_inline` decorator\n",
        "\n",
        "`@always_inline(\"nodebug\")`: same thing but without debug information so you\n",
        "don't step into the + method on Int.\n",
        "\n",
        "### `@parameter` decorator\n",
        "\n",
        "The `@parameter` decorator can be placed on nested functions that capture\n",
        "runtime values to create \"parametric\" capturing closures. This is an unsafe\n",
        "feature in Mojo, because we do not currently model the lifetimes of\n",
        "capture-by-reference. A particular aspect of this feature is that it allows\n",
        "closures that capture runtime values to be passed as parameter values.\n",
        "\n",
        "### Magic operators\n",
        "\n",
        "C++ code has a number of magic operators that intersect with value lifecycle,\n",
        "things like \"placement new\", \"placement delete\" and \"operator=\" that reassign\n",
        "over an existing value. Mojo is a safe language when you use all its language\n",
        "features and compose on top of safe constructs, but of any stack is a world of\n",
        "C-style pointers and rampant unsafety. Mojo is a pragmatic language, and since\n",
        "we are interested in both interoperating with C/C++ and in implementing safe\n",
        "constructs like String directly in Mojo itself, we need a way to express unsafe\n",
        "things.\n",
        "\n",
        "The Mojo standard library `Pointer[element_type]` type is implemented with an\n",
        "underlying `!kgen.pointer<element_type>` type in MLIR, and we desire a way to\n",
        "implement these C++-equivalent unsafe constructs in Mojo. Eventually, these\n",
        "will migrate to all being methods on the Pointer type, but until then, some\n",
        "need to be exposed as built-in operators.\n",
        "\n",
        "<!--\n",
        "TODO: document all of these:\n",
        "\n",
        "```mojo\n",
        "__get_address_as_lvalue(x)\n",
        "__get_address_as_uninit_lvalue(x)\n",
        "__get_lvalue_as_address(x):  use Pointer.address_of instead\n",
        "__get_address_as_owned_value(x)\n",
        "```\n",
        "-->\n",
        "\n",
        "### Direct access to MLIR\n",
        "\n",
        "Mojo provides full access to the MLIR dialects and ecosystem. Please take a\n",
        "look at the [Low level IR in Mojo](/mojo/notebooks/BoolMLIR.html) to learn how\n",
        "to use the `__mlir_type`, `__mlir_op`, and `__mlir_type` constructs. All of the\n",
        "built-in and standard library APIs are implemented by just calling the\n",
        "underlying MLIR constructs, and in doing so, Mojo effectively serves as syntax\n",
        "sugar on top of MLIR.\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Mojo",
      "language": "mojo",
      "name": "mojo-jupyter-kernel"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "mojo"
      },
      "file_extension": ".mojo",
      "mimetype": "text/x-mojo",
      "name": "mojo"
    },
    "orig_nbformat": 4
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
